####

Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

Motivation


According to a recent report, overall tobacco use increased in youths (middle schooland high school students) in the United States in 2017 and 2018, despite previous years of declining use.

This major increase is attributed to an increase in the use of electronic cigaarette (e-cigarette) products.

E-cigarettes are referred to by many different names, including but not limited to:

  1. Electronic nicotine delivery systems (ENDS)
  2. Vapes
  3. e-hookahs
  4. vape pens
  5. tanks
  6. mods

The devices vary greatly:

[source]

See this CDC guide and the American Lung Association website for more information.

The report found that:

During 2017–2018, current use of any tobacco product increased 38.3% (from 19.6% to 27.1%) among high school students and 28.6% (from 5.6% to 7.2%) among middle school students; e-cigarette use increased 77.8% (from 11.7% to 20.8%) among high school students and 48.5% (from 3.3% to 4.9%) among middle school students.

In 2018, the Federal Drug Administration (FDA) in the United States stated that e-cigarette usage use among youth reached:

“nothing short of an epidemic proportion of growth

In this case study, we will be invistigating the same data used in the report that generated the above findings. This data comes from the The National Youth Tobacco Survey (NYTS).

Gentzke, Andrea S., Melisa Creamer, Karen A. Cullen, Bridget K. Ambrose, Gordon Willis, Ahmed Jamal, and Brian A. King. “Vital Signs: Tobacco Product Use Among Middle and High School Students - United States, 2011-2018.” MMWR. Morbidity and Mortality Weekly Report 68 (6): 157–64 (2019).

Main Questions


Our main question:

  1. How has tobacco/nicotine use by American youths changed since 2015?
  2. How do vaping rates compare between males and females?
  3. What vaping brands and flavors appear to be used the most frequently?
    We will base this on the following survey questions:
    > “During the past 30 days, what brand of e-cigarettes did you usually use?”
    >“What flavors of tobacco products have you used in the past 30 days?”

  4. Have vaping rates possibly influenced tobacco/nicotine use?

Learning Objectives


In this case study, we will cover how to import data from multiple files efficiently, how to import data from excel files, and how to make a variety of visualizations to compare multiple groups across time. We will also demonstrate how to work with codebooks. We will cover the concept of survey weighting and introduce the srvyr package. We will discuss the difference between pooled cross-sectional data and panel data. We will especially focus on using packages and functions from the Tidyverse for wrangling data, such as tidyr and dpyr and for visualization, such as as ggplot2. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.


We will begin by loading the packages that we will need:

Package Use
here to easily load and save data
readxl to import the data in the excel files
purrr to import the data in all the different excel and csv files efficiently
readr to import the CSV file data
dplyr to arrange/filter/select/compare specific subsets of the data
summarytools to get an overview of data in a different style
tidyr to rearrange data in wide and long formats

stringr | to manipulate the character strings within the data
ggplot2 | to make visualizations with multiple layers
ggpubr | to easily add regression line equations to plots
forcats | to change details about factors (categorical variables)
lmerTest| to perform linear mixed model testing
car| to perform Levene’s Test of Homogeneity of Variances
ggiraph| to make plots interactive
ggforce| to modify facets in plots
viridis| to plot in color palette
cowplot | to allow plots to be combined skimr | to get an overview of data

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

Context


According to the cited Morbidity and Mortality Weekly Report this was what was already known about this topic and the implications of this study:

Importantly, the vapors used in e-cigarettes contain harmful chemicals:

E-cigarette usage has also been associated with lung injury

See here for additonal information about the potential health effects of e-cigarettes in teens and young adults.

Limitations


There are some important considerations regarding this data analysis to keep in mind:

AVOCADO..Need Michael to look at these…

  1. The data included in the National Youth Tobacco Survey (NYTS) does not follow the same individual students over time. A longitudinal study that does follow the same individuals over time collects data called panel data. The data in this study is called pooled [cross-sectional data]https://en.wikipedia.org/wiki/Cross-sectional_data, this data is obtained from random collection of obervations across time.

According to wikipedia: >Panel data differs from pooled cross-sectional data across time, because it deals with the observations on the same subjects in different times whereas the latter observes different subjects in different time periods

AVOCADO revisit this… 2) The data also includes percentages of students that reported use of particular tobacco product, but the survey questions did not ask how much uses of one product compared to another - for example menthol flavored products where used at the near exclusion of other flavors.

While gender and sex are not actually binary, the data used in this analysis only contains information for groups of individuals who answered the survey questions as male or female.

AVOCADO.. should we drop the race data? we didnt use it… Furthermore, while the race of individual students was surveyed and asked students to self report based on what race or races they considered themselves to be, this list only included the following options:
1) Hispanic, Latino, Latina, or Spanish origin as one single race with the following further options:
1) Mexican, Mexican American, Chicano, or Chicana
2) Puerto Rican
3) Cuban
4) Yes, Another Hispanic, Latino, Latina, or Spanish origin
2)

What are the data?


The data in this case study comes from the National Youth Tobacco Survey (NYTS) which is an annual survey that asks students in high school and middle school (grades 6-12) about tobacco usage in the United States of America.

The data for this survey is freely available online at this website with data from 1999, 2000, 2002, 2004, 2006, 2009, and 2011-2019. We will be using data from 2015-2019 due to the fact that these years are the most recent that asked questions recarding e-cigarette usage.

Each year includes documentation, such as a codebook and an excel file containing the data:

Therefore, since we are using data from 2015-2019, the data we are interested in is located in 5 different excel files, each with their own codebook.

The codebook contains information describing the data within the excel file.

As you can see the excel file contains very short variable names and values, and it is not clear what they mean without the codebook:

The codebook explains what the variables (the columns) are:

And the codebook explains what the values for each variable are:

We will explain more later about what the values on the right indicate.

The reason that there are codebooks for each year is because the questions asked year varied slightly.

The data in this survey is what is called pooled cross-sectional data. In otherwords, different subsets of students are surveyed each year and it is not clear which, if any , individuals particpate from one year to the next.

Data Import


Since these excel files are so large, it takes a bit of time for the data to load. To make the process faster, we previously imported these files, selected only our questions of interest, and saved this data as csv files.

AVOCADO should we drop the race data? we didn’t end up doing anything with this….

Click here for details on how the data was originally imported

First we created a list of filenames of all the different excel files. Using the here() function of the here package, we looked in all the directories of the project. The list.files() function looked for all files with .xlsx within these subdirectories.

[1] "docs/2015-nyts-dataset-and-codebook-microsoft-excel/~$nyts2015.xlsx"
[2] "docs/2015-nyts-dataset-and-codebook-microsoft-excel/nyts2015.xlsx"  
[3] "docs/2016-nyts-dataset-and-codebook-microsoft-excel/nyts2016.xlsx"  
[4] "docs/2017-nyts-dataset-and-codebook-microsoft-excel/nyts2017.xlsx"  
[5] "docs/2018-nyts-dataset-and-codebook-microsoft-excel/nyts2018.xlsx"  
[6] "docs/2019-nyts-dataset-and-codebook-microsoft-excel/nyts2019.xlsx"  

All the files were read using read_excel of the readxl package.Using the map() function of the purrr package this was done efficiently. This created a single list of tibbles (one for each file).

Each excel file name was extracted using the str_extract() function of the stringr package.

[1] "nyts2015" "nyts2015" "nyts2016" "nyts2017" "nyts2018" "nyts2019"

These names became the names of the tibbles in the list of tibbles.

Specific columns were selected from each of the tibbles using the varaible name, as identified in the codebook for being of interest. In some cases functions like starts_with() of the dplyr package were used to select several variables.

tbl[["nyts2015"]] <- tbl[["nyts2015"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Qn1, #Age
                  Qn2, #Sex
                  Qn3, #Grade
                  starts_with("Qn4"), #Hispanic/Latino
                  starts_with("Qn5"), #Race,
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  EFLAVCIGTS,
                  CFLAVCIGTS,
                  EFLAVCIGAR,
                  )

tbl[["nyts2016"]] <- tbl[["nyts2016"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  EFLAVCIGAR,
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  ) 

tbl[["nyts2017"]] <- tbl[["nyts2017"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  CBIDIS,
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  )

tbl[["nyts2018"]] <- tbl[["nyts2018"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  )

tbl[["nyts2019"]] <- tbl[["nyts2019"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  EHTP,
                  CHTP,
                  Q40, #Brang, e-cigarettes
                  Q62A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q62B, #Clove or spice
                  Q62C, #Fruit 
                  Q62D, #Chocolate
                  Q62E, #Alcoholic Drink
                  Q62F, #Candy/Desserts/Other Sweets
                  Q62G, #Some Other Flavor Not Listed Here 
                  )

A directory was created using the base dir.create() function called data_reduced for the csv files. New csv files were created for each of the tbls in the list using the write_csv() function of the readr package. This was done all at once using the base mappy() function.

Now we will show how to read in the data from the five CSV files that were created from the five different excel files.

Reading in the CSV files

nyts_data[["nyts2016"]] <- nyts_data[["nyts2016"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  -EFLAVCIGAR,
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  ) %>%
    rename(Age=Q1,
           female=Q2,
           Grade=Q3,
           Not_HL=Q4A,
           HL_Mex=Q4B,
           HL_PR=Q4C,
           HL_Cub=Q4D,
           HL_Other=Q4E,
           Race_AIAN=Q5A,
           Race_Asian=Q5B,
           Race_BAA=Q5C,
           Race_NHOPI=Q5D,
           Race_White=Q5E,
           female=Q2,
           menthol=Q50A,
           clove_spice=Q50B,
           fruit=Q50C,
           chocolate=Q50D,
           alcoholic_drink=Q50E,
           candy_dessert_sweets=Q50F,
           other=Q50G,
           no_use=Q50H) %>%
    mutate(Age = as.numeric(Age) + 8,
           Grade = as.numeric(Grade) + 5,
           brand_ecig=NA) %>%
  dplyr::select(-starts_with("Q"))

# sapply(nyts_data[["nyts2016"]], function(x)
#     summary(
#         factor(x)
#         )
#     )

nyts_data[["nyts2016"]] <- nyts_data[["nyts2016"]] %>%
  mutate_all(~ replace(., . %in% c("*", "**"), NA)) %>%
  mutate(Age=as.character(Age),
         Grade=as.character(Grade)
         ) %>%
  mutate(Age=recode(Age,
                    `19` = ">18",
                    ),
         female=recode(female,
                      `1`= FALSE,
                      `2` = TRUE,
                      .default = NA,
                      .missing = NA),
         Grade=recode(Grade,
                      `13` = "Ungraded/Other"),
         Not_HL=recode(Not_HL,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE)) %>%
  mutate_at(vars(starts_with("HL", ignore.case = FALSE)),
              list(~recode(.,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
  mutate_at(vars(starts_with("Race", ignore.case = FALSE)),
              list(~recode(.,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
    mutate_at(vars(starts_with("E", ignore.case = FALSE),
                   starts_with("C", ignore.case = FALSE)),
              list(~recode(.,
                           `1` = TRUE,
                           `2` = FALSE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
    mutate_at(vars(menthol:no_use),
              list(~recode(.,
                           `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE)))

# sapply(nyts_data[["nyts2016"]], function(x)
#     summary(
#         factor(x)
#         )
#     )
nyts_data[["nyts2017"]] <- nyts_data[["nyts2017"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  CBIDIS,
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  ) %>%
    rename(Age=Q1,
           female=Q2,
           Grade=Q3,
           Not_HL=Q4A,
           HL_Mex=Q4B,
           HL_PR=Q4C,
           HL_Cub=Q4D,
           HL_Other=Q4E,
           Race_AIAN=Q5A,
           Race_Asian=Q5B,
           Race_BAA=Q5C,
           Race_NHOPI=Q5D,
           Race_White=Q5E,
           female=Q2,
           menthol=Q50A,
           clove_spice=Q50B,
           fruit=Q50C,
           chocolate=Q50D,
           alcoholic_drink=Q50E,
           candy_dessert_sweets=Q50F,
           other=Q50G,
           no_use=Q50H) %>%
    mutate(Age = as.numeric(Age) + 8,
           Grade = as.numeric(Grade) + 5,
           brand_ecig=NA) %>%
  dplyr::select(-starts_with("Q"))

# sapply(nyts_data[["nyts2017"]], function(x)
#     summary(
#         factor(x)
#         )
#     )

nyts_data[["nyts2017"]] <- nyts_data[["nyts2017"]] %>%
  mutate_all(~ replace(., . %in% c("*", "**"), NA)) %>%
  mutate(Age=as.character(Age),
         Grade=as.character(Grade)
         ) %>%
  mutate(Age=recode(Age,
                    `19` = ">18",
                    ),
         female=recode(female,
                      `1`= FALSE,
                      `2` = TRUE,
                      .default = NA,
                      .missing = NA),
         Grade=recode(Grade,
                      `13` = "Ungraded/Other"),
         Not_HL=recode(Not_HL,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE)) %>%
  mutate_at(vars(starts_with("HL", ignore.case = FALSE)),
              list(~recode(.,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
  mutate_at(vars(starts_with("Race", ignore.case = FALSE)),
              list(~recode(.,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
    mutate_at(vars(starts_with("E", ignore.case = FALSE),
                   starts_with("C", ignore.case = FALSE)),
              list(~recode(.,
                           `1` = TRUE,
                           `2` = FALSE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
    mutate_at(vars(menthol:no_use),
              list(~recode(.,
                           `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE)))

# sapply(nyts_data[["nyts2017"]], function(x)
#     summary(
#         factor(x)
#         )
#     )
nyts_data[["nyts2018"]] <- nyts_data[["nyts2018"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  Q50A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q50B, #Clove or spice
                  Q50C, #Fruit
                  Q50D, #Chocolate
                  Q50E, #Alcoholic Drink
                  Q50F, #Candy/Desserts/Other Sweets
                  Q50G, #Some Other Flavor Not Listed Here
                  Q50H #I Did Not Use Flavored Tobacco Products In the Past
                  ) %>%
    rename(Age=Q1,
           female=Q2,
           Grade=Q3,
           Not_HL=Q4A,
           HL_Mex=Q4B,
           HL_PR=Q4C,
           HL_Cub=Q4D,
           HL_Other=Q4E,
           Race_AIAN=Q5A,
           Race_Asian=Q5B,
           Race_BAA=Q5C,
           Race_NHOPI=Q5D,
           Race_White=Q5E,
           female=Q2,
           menthol=Q50A,
           clove_spice=Q50B,
           fruit=Q50C,
           chocolate=Q50D,
           alcoholic_drink=Q50E,
           candy_dessert_sweets=Q50F,
           other=Q50G,
           no_use=Q50H) %>%
    mutate(Age = as.numeric(Age) + 8,
           Grade = as.numeric(Grade) + 5,
           brand_ecig=NA) %>%
  dplyr::select(-starts_with("Q"))

# sapply(nyts_data[["nyts2018"]], function(x)
#     summary(
#         factor(x)
#         )
#     )

nyts_data[["nyts2018"]] <- nyts_data[["nyts2018"]] %>%
  mutate_all(~ replace(., . %in% c("*", "**"), NA)) %>%
  mutate(Age=as.character(Age),
         Grade=as.character(Grade)
         ) %>%
    mutate(Age=recode(Age,
                    `19` = ">18",
                    ),
         female=recode(female,
                      `1`= FALSE,
                      `2` = TRUE,
                      .default = NA,
                      .missing = NA),
         Grade=recode(Grade,
                      `13` = "Ungraded/Other"),
         Not_HL=recode(Not_HL,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE)) %>%
  mutate_at(vars(starts_with("HL", ignore.case = FALSE)),
              list(~recode(.,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
  mutate_at(vars(starts_with("Race", ignore.case = FALSE)),
              list(~recode(.,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
  mutate_at(vars(starts_with("E", ignore.case = FALSE),
                   starts_with("C", ignore.case = FALSE)),
            list(~recode(.,
                         `1` = TRUE,
                         `2` = FALSE,
                         .missing = NA))) %>%
    mutate_at(vars(menthol:no_use),
              list(~recode(.,
                           `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE)))

# sapply(nyts_data[["nyts2018"]], function(x)
#     summary(
#         factor(x)
#         )
#     )
nyts_data[["nyts2019"]] <- nyts_data[["nyts2019"]] %>%
    dplyr::select(psu,
                  finwgt,
                  stratum,
                  Q1, #Age
                  Q2, #Sex
                  Q3, #Grade
                  starts_with("Q4"), #Hispanic/Latino
                  starts_with("Q5"), #Race
                  starts_with("E",
                              ignore.case = FALSE),
                  starts_with("C",
                              ignore.case = FALSE),
                  -EHTP,
                  -CHTP,
                  Q40, #Brang, e-cigarettes
                  Q62A, #Menthol # What flavors of tobacco products have you used in the past 30 days? (Select one or more)
                  Q62B, #Clove or spice
                  Q62C, #Fruit 
                  Q62D, #Chocolate
                  Q62E, #Alcoholic Drink
                  Q62F, #Candy/Desserts/Other Sweets
                  Q62G, #Some Other Flavor Not Listed Here 
                  )  %>%
    rename(brand_ecig=Q40,
           Age=Q1,
           female=Q2,
           Grade=Q3,
           Not_HL=Q4A,
           HL_Mex=Q4B,
           HL_PR=Q4C,
           HL_Cub=Q4D,
           HL_Other=Q4E,
           Race_AIAN=Q5A,
           Race_Asian=Q5B,
           Race_BAA=Q5C,
           Race_NHOPI=Q5D,
           Race_White=Q5E,
           female=Q2,
           menthol=Q62A,
           clove_spice=Q62B,
           fruit=Q62C,
           chocolate=Q62D,
           alcoholic_drink=Q62E,
           candy_dessert_sweets=Q62F,
           other=Q62G) %>%
    mutate(Age = as.numeric(Age) + 8,
           Grade = as.numeric(Grade) + 5,
           no_use="missing") %>%
  dplyr::select(-starts_with("Q"))

# sapply(nyts_data[["nyts2019"]], function(x)
#     summary(
#         factor(x)
#         )
#     )

nyts_data[["nyts2019"]] <- nyts_data[["nyts2019"]] %>%
  mutate_all(~ replace(., . %in% c(".N",".S",".Z"), NA)) %>%
  mutate(Age=as.character(Age),
         Grade=as.character(Grade)
         ) %>%
  mutate(psu=as.character(psu),
         Age=recode(Age,
                    `19` = ">18",
                    ),
         female=recode(female,
                      `1`= FALSE,
                      `2` = TRUE,
                      .default = NA),
         Grade=recode(Grade,
                      `13` = "Ungraded/Other"),
         Not_HL=recode(Not_HL,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE)) %>%
  mutate_at(vars(starts_with("HL", ignore.case = FALSE)),
              list(~recode(.,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
  mutate_at(vars(starts_with("Race", ignore.case = FALSE)),
              list(~recode(.,
                       `1` = TRUE,
                       .default = FALSE,
                      .missing = FALSE))) %>%
    mutate_at(vars(starts_with("E", ignore.case = FALSE),
                   starts_with("C", ignore.case = FALSE)),
              list(~recode(.,
                           `1` = TRUE,
                           `2` = FALSE,
                           .default = NA))) %>%
    mutate(brand_ecig = recode(brand_ecig,
                                             `1` = "Other", #levels 1,8 combined to `Other` 
                                             `2` = "Blu",
                                             `3` = "JUUL",
                                             `4` = "Logic",
                                             `5` = "MarkTen",
                                             `6` = "NJOY",
                                             `7` = "Vuse",
                                             `8` = "Other")) %>%
    mutate_at(vars(menthol:no_use),
              list(~recode(.,
                           `1` = TRUE,
                           .default = FALSE,
                           .missing =FALSE))) #Ask Michael about this if unclear

# sapply(nyts_data[["nyts2019"]], function(x)
#     summary(
#         factor(x)
#         )
#     )

Reminder: Current users are a subset of ever users.

Data Exploration and Wrangling


We will also use the %>% pipe which can be used to define the input for later sequential steps. This will make more sense when we have multiple sequential steps using the same data object. To use the pipe notation we need to install and load dplyr as well.

Data Visualization


Question 1

For lots of pivot_longer() that are the same… can use pivot_longer_spec()

spec <- relig_income %>% build_longer_spec( cols = -religion, names_to = “income”, values_to = “count” ) pivot_longer_spec(relig_income, spec)

But need to decide if we are going to create some new data frames…

Question 3

What vaping brands and flavors appear to be used the most frequently?

Huang J, Duan Z, Kwok J, et al. Tob Control 2019;28:146–151.

Huang J, Duan Z, Kwok J, et al. Tob Control 2019;28:146–151.

Paper

plot5 <- nyts_data %>%
  filter(year!=2015) %>%
  filter(menthol==TRUE|
           clove_spice==TRUE|
           fruit==TRUE|
           chocolate==TRUE|
           alcoholic_drink==TRUE|
           candy_dessert_sweets==TRUE|
           other==TRUE) %>%
  mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  mutate(ecig_only_ever = case_when(ecig_ever == TRUE &
                                      non_ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE),
           ecig_only_current = case_when(ecig_current == TRUE &
                                           non_ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE),
           non_ecig_only_ever = case_when(non_ecig_ever == TRUE &
                                            ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE),
           non_ecig_only_current = case_when(non_ecig_current == TRUE &
                                               ecig_ever ==FALSE ~ TRUE,
                                    TRUE ~ FALSE)) %>%
  mutate(Group = case_when(ecig_only_ever==TRUE |
                             ecig_only_current==TRUE ~ "Only e-cigarettes",
                         non_ecig_only_ever==TRUE |
                           non_ecig_only_current==TRUE ~ "Only other products",
                                    TRUE ~ "Both")) %>%
  filter(Group!="Both") %>%
  group_by(year, Group) %>%
  summarise(`Menthol`=(sum(menthol, na.rm = TRUE)*100)/
              sum(!is.na(menthol)),
              `Clove or Spice`=(sum(clove_spice, na.rm = TRUE)*100)/
              sum(!is.na(clove_spice)),
              `Fruit`=(sum(fruit, na.rm = TRUE)*100)/sum(!is.na(fruit)),
              `Chocolate`=(sum(chocolate, na.rm = TRUE)*100)/
              sum(!is.na(chocolate)),
              `Alcoholic Drink`=(sum(alcoholic_drink, na.rm = TRUE)*100)/
              sum(!is.na(alcoholic_drink)),
              `Candy/Desserts/Sweets`=(sum(candy_dessert_sweets, na.rm = TRUE)*100)/
              sum(!is.na(candy_dessert_sweets)),
            `Other`=(sum(other, na.rm = TRUE)*100)/
              sum(!is.na(other)),
            Respondents=n()) %>%
  #converting all columns between and including Menthol and Other to one column called Flavor
  pivot_longer(cols = Menthol:Other, names_to = "Flavor", values_to = "Percentage of students") %>%
  filter(!is.na(`Percentage of students`),
         Flavor!="Other") %>%
  group_by(Flavor) %>%
  mutate(affirmative=(Respondents * `Percentage of students`)/100) %>%
  mutate(flavor_mean = sum(affirmative)/sum(Respondents)) %>%
  ungroup() %>%
  mutate(flavor_mean_rank = dense_rank(flavor_mean),
         Flavor = fct_reorder(Flavor, flavor_mean_rank)) %>%
  ggplot(aes(x=year, y=`Percentage of students`, color=Group)) +
  facet_wrap(.~Flavor,ncol=3) +
  geom_line() + 
  geom_point(show.legend = FALSE) + 
  theme_minimal() +
  theme(legend.position = "bottom",
          axis.title.x = element_blank(),
        axis.text.x = element_text(angle = 90)) + 
  labs(title = "Among users of only one type of product, what vaping flavors appear to be used the most frequently?",
       subtitle = "Percent reporting only e-cigarette use vs only other nicotine product use")

plot5

Question 4

Have vaping rates possibly influenced tobacco/nicotine use?

plot7 <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
    group_by(year) %>%
    summarise(ecig_ever_year=(sum(ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(ecig_ever)),
              ecig_current_year=(sum(ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(ecig_current)),
              non_ecig_ever_year=(sum(non_ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_ever)),
              non_ecig_current_year=(sum(non_ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_current))) %>%
    pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    mutate(User = case_when(Category =="ecig_ever_year" ~ "Ever",
                           Category =="non_ecig_ever_year" ~ "Ever",
                           Category =="ecig_current_year" ~ "Current",
                           Category =="non_ecig_current_year" ~ "Current")) %>%
    mutate(Product = case_when(Category =="ecig_ever_year" ~ "E-cigarettes",
                           Category =="non_ecig_ever_year" ~ "Other products",
                           Category =="ecig_current_year" ~ "E-cigarettes",
                           Category =="non_ecig_current_year" ~ "Other products")) %>%
    filter(User=="Ever") %>%
    ggplot(aes(x=year,y=`Percentage of students`, color=Product)) +
    geom_line(linetype=1) + # geom_bar(stat="identity", position = "dodge", color="black") +
  geom_point(show.legend = FALSE) +
  scale_y_continuous(breaks = seq(10, 60, by = 10), limits = c(10,60)) +
    theme_minimal() +
    theme(legend.position = "bottom",
          axis.title.x = element_blank()) +
    labs(title = "How does e-cigarette ever use compare to ever use of other products over the years?",
         subtitle = "E-cigarette and non-e-cigarette use",
         y = "% of students")

plot7

plot8 <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
    group_by(year) %>%
    summarise(ecig_ever_year=(sum(ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(ecig_ever)),
              ecig_current_year=(sum(ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(ecig_current)),
              non_ecig_ever_year=(sum(non_ecig_ever, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_ever)),
              non_ecig_current_year=(sum(non_ecig_current, na.rm = TRUE)*100)/
                sum(!is.na(non_ecig_current))) %>%
    pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year) %>%
    mutate(User = case_when(Category =="ecig_ever_year" ~ "Ever",
                           Category =="non_ecig_ever_year" ~ "Ever",
                           Category =="ecig_current_year" ~ "Current",
                           Category =="non_ecig_current_year" ~ "Current")) %>%
    mutate(Product = case_when(Category =="ecig_ever_year" ~ "E-cigarettes",
                           Category =="non_ecig_ever_year" ~ "Other products",
                           Category =="ecig_current_year" ~ "E-cigarettes",
                           Category =="non_ecig_current_year" ~ "Other products")) %>%
    ggplot(aes(x=year,y=`Percentage of students`, color=Product, linetype=User)) +
    geom_line() +
  geom_point(show.legend = FALSE) +
  scale_linetype_manual(values = c(2,1)) +
  scale_y_continuous(breaks = seq(0, 60, by = 10), limits = c(0,60)) +
    theme_minimal() +
    theme(legend.position = "bottom",
          axis.title.x = element_blank()) +
    labs(title = "How does e-cigarette use compare to use of other products over the years?",
         subtitle = "E-cigarette and non-e-cigarette use",
         y = "% of students")

plot8

Weighted Sample

plotA_w <- nyts_data %>%
    mutate(tobacco_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE),
           tobacco_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(tobacco_ever = case_when(tobacco_sum_ever > 0 ~ TRUE,
                                    tobacco_sum_ever ==0 ~ FALSE),
           tobacco_current = case_when(tobacco_sum_current > 0 ~ TRUE,
                                    tobacco_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt, nest=TRUE) %>%
    group_by(year) %>%
  summarise(tobacco_ever_year = survey_mean(tobacco_ever, vartype = "ci", na.rm=TRUE),
            tobacco_current_year = survey_mean(tobacco_current, vartype = "ci", na.rm=TRUE))  %>%
  mutate_at(vars(-year), "*", 100) %>%
    pivot_longer(cols = -year, names_to = "Type", values_to = "Percentage of students") %>%
    # gather(key=Type,
    #        value=`Percentage of students`,
    #        -year) %>%
  mutate(Estimate = case_when(grepl("_low", Type) ~ "Lower",
                          grepl("_upp", Type) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Type) ~ "Ever",
                          grepl("current", Type) ~ "Current",
                          TRUE ~ "Mean")) %>%
  dplyr::select(-Type) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  ggplot(aes(x=year,y=Mean)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper), show.legend = FALSE) +
  scale_linetype_manual(values = c(2,1)) +
    scale_y_continuous(breaks = seq(0,70,by=10),
                       labels = seq(0,70,by=10),
                       limits = c(0,70)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "Nicotine product users more prevalent after 2017",
         y = "% of students")

plotB_w <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt, nest=TRUE) %>%
    group_by(year) %>%
    summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
  pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year)  %>%
  mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("current", Category) ~ "Current",
                          TRUE ~ "Ever",),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  filter(User=="Ever") %>%
  dplyr::rename("Lower_temp" = Upper,
                "Upper_temp" = Lower) %>%
  dplyr::rename("Lower"=Lower_temp,
                "Upper"=Upper_temp) %>%
    ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(linetype=1) +
  geom_linerange(aes(ymin = Lower, ymax = Upper), show.legend = FALSE) +
  scale_y_continuous(breaks = seq(10, 60, by = 10), limits = c(10,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "% ever trying e-cigarettes increases &\n% ever trying other products decreases",
         y = "% of students")

#### the wrangling looks the same as the above plot...
plotC_w <- nyts_data %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt, nest=TRUE) %>%
    group_by(year) %>%
  summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
  pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students") %>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year) %>%
    mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Category) ~ "Ever",
                          grepl("current", Category) ~ "Current"),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
    ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper), show.legend = FALSE) +
  scale_linetype_manual(values = c(2,1)) +
  scale_y_continuous(breaks = seq(0, 60, by = 10), limits = c(0,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "% Using e-cigarettes increases &\n% using Other products decreases",
         y = "% of students")

title_w <- ggdraw() + 
  draw_label(
    expression("Have vaping rates possibly influenced tobacco/nicotine use?"),
    fontface = 'bold',
    size=14,
    x = 0,
    hjust = 0
  ) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsA_w <- plot_grid(plotA_w,
                     rel_widths = c(1),
                     align = "v",
                     axis = "bt")
plotsBC_w <- plot_grid(plotB_w,
                     plotC_w,
                     rel_widths = c(1,1),
                     align = "v",
                     axis = "bt")

legend_w <- get_legend(plotB_w +
                       theme(legend.position = "bottom",
                             legend.direction = "horizontal"))

figure_w <- plot_grid(title_w,
                      plotsA_w,
                      plotsBC_w,
                      legend_w,
                      ncol = 1,
                      rel_heights = c(0.1,
                                      1,
                                      1,
                                      0.1),
                      scale = 1.0)

figure_w

Hypothethical Cohort

plotA_w_8 <- nyts_data %>%
  filter((Grade == "8" & year == 2015) |
         (Grade == "9" & year == 2016) |
         (Grade == "10" & year == 2017) |
         (Grade == "11" & year == 2018) |
          (Grade == "12" & year == 2019) 
         ) %>%
    mutate(tobacco_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE),
           tobacco_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(tobacco_ever = case_when(tobacco_sum_ever > 0 ~ TRUE,
                                    tobacco_sum_ever ==0 ~ FALSE),
           tobacco_current = case_when(tobacco_sum_current > 0 ~ TRUE,
                                    tobacco_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt) %>%
    group_by(year) %>%
  summarise(tobacco_ever_year = survey_mean(tobacco_ever, vartype = "ci", na.rm=TRUE),
            tobacco_current_year = survey_mean(tobacco_current, vartype = "ci", na.rm=TRUE))  %>%
  mutate_at(vars(-year), "*", 100) %>%
    pivot_longer(cols = -year, names_to = "Type", values_to = "Percentage of students")%>%
    # gather(key=Type,
    #        value=`Percentage of students`,
    #        -year) %>%
  mutate(Estimate = case_when(grepl("_low", Type) ~ "Lower",
                          grepl("_upp", Type) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Type) ~ "Ever",
                          grepl("current", Type) ~ "Current",
                          TRUE ~ "Mean")) %>%
  dplyr::select(-Type) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  ggplot(aes(x=year,y=Mean)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper)) + 
  scale_linetype_manual(values = c(2,1)) +
    scale_y_continuous(breaks = seq(0,70,by=10),
                       labels = seq(0,70,by=10),
                       limits = c(0,70)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "Nicotine product users becoming increasingly prevalent",
         y = "% of students")

plotB_w_8 <- nyts_data %>%
  filter((Grade == "8" & year == 2015) |
         (Grade == "9" & year == 2016) |
         (Grade == "10" & year == 2017) |
         (Grade == "11" & year == 2018) |
          (Grade == "12" & year == 2019) 
         ) %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt) %>%
    group_by(year) %>%
    summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
   pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students")%>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year)  %>%
  mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("current", Category) ~ "Current",
                          TRUE ~ "Ever",),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
  filter(User=="Ever") %>%
  dplyr::rename("Lower_temp" = Upper,
                "Upper_temp" = Lower) %>%
  dplyr::rename("Lower"=Lower_temp,
                "Upper"=Upper_temp) %>%
  ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(linetype=1) +
  geom_linerange(aes(ymin = Lower, ymax = Upper)) + 
  scale_y_continuous(breaks = seq(10, 60, by = 10), limits = c(10,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "% ever trying nicotine products increases",
         y = "% of students")

plotC_w_8 <- nyts_data %>%
  filter((Grade == "8" & year == 2015) |
         (Grade == "9" & year == 2016) |
         (Grade == "10" & year == 2017) |
         (Grade == "11" & year == 2018) |
          (Grade == "12" & year == 2019) 
         ) %>%
    mutate(ecig_sum_ever = select(., EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           ecig_sum_current = select(., CELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_ever = select(., starts_with("E", ignore.case = FALSE)) %>%
               select(.,-EELCIGT) %>%
               apply(1, sum, na.rm=TRUE),
           non_ecig_sum_current = select(., starts_with("C", ignore.case = FALSE)) %>%
               select(.,-CELCIGT) %>%
               apply(1, sum, na.rm=TRUE)) %>%
    mutate(ecig_ever = case_when(ecig_sum_ever > 0 ~ TRUE,
                                    ecig_sum_ever ==0 ~ FALSE),
           ecig_current = case_when(ecig_sum_current > 0 ~ TRUE,
                                    ecig_sum_current ==0 ~ FALSE),
           non_ecig_ever = case_when(non_ecig_sum_ever > 0 ~ TRUE,
                                    non_ecig_sum_ever ==0 ~ FALSE),
           non_ecig_current = case_when(non_ecig_sum_current > 0 ~ TRUE,
                                    non_ecig_sum_current ==0 ~ FALSE)) %>%
  as_survey_design(strata = stratum, ids = psu, weight  = finwgt) %>%
    group_by(year) %>%
  summarise(ecig_ever_year = survey_mean(ecig_ever, vartype = "ci", na.rm=TRUE),
            ecig_current_year = survey_mean(ecig_current, vartype = "ci", na.rm=TRUE),
            non_ecig_ever_year = survey_mean(non_ecig_ever, vartype = "ci", na.rm=TRUE),
            non_ecig_current_year = survey_mean(non_ecig_current, vartype = "ci", na.rm=TRUE)) %>%
  mutate_at(vars(-year), "*", 100) %>%
  dplyr::select(year,
                ecig_ever_year,
                ecig_current_year,
                non_ecig_ever_year,
                non_ecig_current_year,
                contains("low"),
                contains("upp")) %>%
  pivot_longer(cols = -year, names_to = "Category", values_to = "Percentage of students")%>%
    # gather(key=Category,
    #        value=`Percentage of students`,
    #        -year) %>%
    mutate(Estimate = case_when(grepl("_low", Category) ~ "Lower",
                          grepl("_upp", Category) ~ "Upper",
                          TRUE ~ "Mean"),
         User = case_when(grepl("ever", Category) ~ "Ever",
                          grepl("current", Category) ~ "Current"),
         Product = case_when(grepl("non_ecig", Category) ~ "Other products",
                          TRUE ~ "E-cigarettes")) %>%
  dplyr::select(-Category) %>%
  pivot_wider(names_from = Estimate, 
              values_from = `Percentage of students`) %>%
  #spread(Estimate, `Percentage of students`) %>%
    ggplot(aes(x=year,y=Mean, color=Product)) +
  geom_line(aes(linetype=User)) +
  geom_linerange(aes(ymin = Lower, ymax = Upper)) + 
  scale_linetype_manual(values = c(2,1)) +
  scale_y_continuous(breaks = seq(0, 60, by = 10), limits = c(0,60)) +
    theme_minimal() +
    theme(legend.position = "none",
          axis.title.x = element_blank()) +
    labs(title = "E-cigarette use surpasses use of other nicotine products",
         y = "% of students")

title_w_8 <- ggdraw() + 
  draw_label(
    expression("Among"~8^th~"graders in 2015, have vaping rates possibly influenced tobacco/nicotine use?"),
    fontface = 'bold',
    size=14,
    x = 0,
    hjust = 0
  ) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsA_w_8 <- plot_grid(plotA_w_8,
                        rel_widths = c(1),
                        align = "v",
                        axis = "bt")

plotsBC_w_8 <- plot_grid(plotB_w_8,
                         plotC_w_8,
                         rel_widths = c(1,1),
                         axis = "bt")

legend_w_8 <- get_legend(plotB_w_8 +
                       theme(legend.position = "bottom",
                             legend.direction = "horizontal"))

figure_w_8 <- plot_grid(title_w_8,
                        plotsA_w_8,
                        plotsBC_w_8,
                        legend_w_8,
                        ncol = 1,
                        rel_heights = c(0.1,
                                      1,
                                      1,
                                      0.1),
                        scale = 1.0
)

figure_w_8

Final Figure

title_final <- ggdraw() +
  draw_label(
    expression("Have vaping rates possibly influenced tobacco/nicotine use?"),
    fontface = 'bold',
    size=16,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_uw_final <- ggdraw() + 
  draw_label(
    expression(~6^th~"-"~12^th~"graders, unweighted"),
    size=12,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_w_final <- ggdraw() + 
  draw_label(
    expression(~6^th~"-"~12^th~"graders, weighted"),
    fontface = 'bold',
    size=12,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_w_8_final <- ggdraw() + 
  draw_label(
    expression(~8^th~"graders in 2015, weighted"),
    fontface = 'bold',
    size=12,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

subtitle_final <- plot_grid(subtitle_uw_final,
                            subtitle_w_final,
                            subtitle_w_8_final,
                            ncol = 3)

plotsA_title_final <- ggdraw() + 
  draw_label(
    expression("Prevalence of e-cigarette use by user type"),
    size=14,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsA_final <- plot_grid(plotA_uw + theme(plot.title = element_blank()),
                          plotA_w + theme(plot.title = element_blank()),
                          plotA_w_8 + theme(plot.title = element_blank()),
                          ncol = 3,
                          align = "v",
                          axis = "bt")

plotsB_title_final <- ggdraw() + 
  draw_label(
    expression("Prevalence of ever use by product type"),
    size=14,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsB_final <- plot_grid(plotB_uw + theme(plot.title = element_blank()),
                          plotB_w + theme(plot.title = element_blank()),
                          plotB_w_8 + theme(plot.title = element_blank()),
                          ncol = 3,
                          align = "v",
                          axis = "bt")

plotsC_title_final <- ggdraw() + 
  draw_label(
    expression("Prevalence of nicotine product use by product & user type"),
    size=14,
    x = 0.5) +
  theme(
    plot.margin = margin(0, 0, 0, 0)
  )

plotsC_final <- plot_grid(plotC_uw + theme(plot.title = element_blank()),
                          plotC_w + theme(plot.title = element_blank()),
                          plotC_w_8 + theme(plot.title = element_blank()),
                          ncol = 3,
                          align = "v",
                          axis = "bt")

legend_final <- get_legend(plotB_w +
                             theme(legend.position = "bottom",
                             legend.direction = "horizontal"))

final_plot <- plot_grid(title_final,
          plotsA_title_final,
          subtitle_final,
          plotsA_final,
          plotsB_title_final,
          subtitle_final,
          plotsB_final,
          plotsC_title_final,
          subtitle_final,
          plotsC_final,
          legend_final,
          ncol = 1,
          rel_heights = c(0.2,
                          0.2,
                          0.1,
                          1,
                          0.2,
                          0.1,
                          1,
                          0.2,
                          0.1,
                          1,
                          0.1))

final_plot

Suggested Homework


  • Apply survey weights to one of the figures produced in this case study in which weighted estimates were not produced. Include error bars in the updated figure.
    • Does the figure change after the application of survey weights?
    • If so, describe how.
  • Reproduce final_plot above for a different cohort of your choice.

Notes

Ever and current variables are limited to those shared by all years of data included in this case study.

New code: Knit time: 33.841 secs. Previous code: ~ 3 m.

Problems

I had difficulty producing a plot that succinctly presented a trend. It’s very easy to produce plots that are very useful once one is familiar with the data. Some plots, however, cannot stand alone and need additional context to be clear for those without prior knowledge of the data. When I first shared a plot I had been working on with others, it became clear that in my effort to present a complicated idea briefly I had left out information that would make the trend easily interpretable. To solve this issue, I began to present visualizations of the data alongside my original plot. The final figure I created contained several additional plots, each presenting the same trend at a different level than my initial plot.

My “centerpiece” plot is the middle plot in final_plot. The 8 plots around it help provide a very clear picture of what is going on in the US with regards to e-cigarette use and nicotine product use at large. On its own, it’s difficult to understand the trends in the US and how important the weighting scheme is for inference. Once you add the left and right columns, it’s clear what is going on.

Data Analysis


content header


Summary


Session info


R version 4.0.1 (2020-06-06)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Mojave 10.14.5

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] cowplot_1.0.0      ggplot2_3.3.1      srvyr_0.3.10       summarytools_0.9.6
 [5] readr_1.3.1        forcats_0.5.0      tidyr_1.1.0        stringr_1.4.0     
 [9] dplyr_1.0.0        purrr_0.3.4        readxl_1.3.1       knitr_1.28        
[13] here_0.1          

loaded via a namespace (and not attached):
 [1] tidyselect_1.1.0   xfun_0.14          pander_0.6.3       mitools_2.4       
 [5] splines_4.0.1      lattice_0.20-41    tcltk_4.0.1        colorspace_1.4-1  
 [9] vctrs_0.3.0        generics_0.0.2     htmltools_0.4.0    yaml_2.2.1        
[13] base64enc_0.1-3    survival_3.1-12    rlang_0.4.6        pillar_1.4.4      
[17] glue_1.4.1         withr_2.2.0        DBI_1.1.0          pryr_0.1.4        
[21] matrixStats_0.56.0 lifecycle_0.2.0    plyr_1.8.6         munsell_0.5.0     
[25] gtable_0.3.0       cellranger_1.1.0   codetools_0.2-16   evaluate_0.14     
[29] labeling_0.3       highr_0.8          Rcpp_1.0.4.6       backports_1.1.7   
[33] scales_1.1.1       checkmate_2.0.0    magick_2.3         farver_2.0.3      
[37] rapportools_1.0    hms_0.5.3          digest_0.6.25      stringi_1.4.6     
[41] survey_4.0         rprojroot_1.3-2    grid_4.0.1         tools_4.0.1       
[45] magrittr_1.5       tibble_3.0.1       crayon_1.3.4       pkgconfig_2.0.3   
[49] ellipsis_0.3.1     Matrix_1.2-18      lubridate_1.7.8    rmarkdown_2.2     
[53] R6_2.4.1           compiler_4.0.1    
LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBWYXBpbmcgQmVoYXZpb3JzIGluIEFtZXJpY2FuIFlvdXRoIgphdXRob3I6ICJNaWNoYWVsIE9udGl2ZXJvcywgQ2FycmllIFdyaWdodCwgUGhELiAiCgpjc3M6IHN0eWxlLmNzcwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwoKLS0tCjxzdHlsZT4KI1RPQyB7CiAgYmFja2dyb3VuZDogdXJsKCJodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vaW1nL2xvZ28uanBnIik7CiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOwogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50OwogIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7Cn0KPC9zdHlsZT4KCmBgYHtyLCBlY2hvPUZBTFNFfQprbml0X3RpbWVfc3RhcnQgPC0gU3lzLnRpbWUoKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTgsIGRwaT0zMDApIApgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSwgY2FjaGUgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbiA9ICJjZW50ZXIiLCBvdXQud2lkdGggPSAnOTAlJykKbGlicmFyeShoZXJlKQpsaWJyYXJ5KGtuaXRyKQpgYGAKCgojIyMjIHsub3V0bGluZSB9CmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aCA9ICI4MDAgcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiZmluYWxfcGxvdC5wbmciKSkKYGBgCiMjIyMKCgoKCiMjIHsuZGlzY2xhaW1lcl9ibG9ja30KCioqRGlzY2xhaW1lcioqOiBUaGUgcHVycG9zZSBvZiB0aGUgW09wZW4gQ2FzZSBTdHVkaWVzXShodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8pe3RhcmdldD0iX2JsYW5rIn0gcHJvamVjdCBpcyAqKnRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdmFyaW91cyBkYXRhIHNjaWVuY2UgbWV0aG9kcywgdG9vbHMsIGFuZCBzb2Z0d2FyZSBpbiB0aGUgY29udGV4dCBvZiBtZXNzeSwgcmVhbC13b3JsZCBkYXRhKiouIEEgZ2l2ZW4gY2FzZSBzdHVkeSBkb2VzIG5vdCBjb3ZlciBhbGwgYXNwZWN0cyBvZiB0aGUgcmVzZWFyY2ggcHJvY2VzcywgaXMgbm90IGNsYWltaW5nIHRvIGJlIHRoZSBtb3N0IGFwcHJvcHJpYXRlIHdheSB0byBhbmFseXplIGEgZ2l2ZW4gZGF0YSBzZXQsIGFuZCBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhlIGNvbnRleHQgb2YgbWFraW5nIHBvbGljeSBkZWNpc2lvbnMgd2l0aG91dCBleHRlcm5hbCBjb25zdWx0YXRpb24gZnJvbSBzY2llbnRpZmljIGV4cGVydHMuIAoKIyMgKipNb3RpdmF0aW9uKioKKioqIApBY2NvcmRpbmcgdG8gYSByZWNlbnQgW3JlcG9ydF0oaHR0cHM6Ly93d3cuY2RjLmdvdi9tbXdyL3ZvbHVtZXMvNjgvd3IvbW02ODA2ZTEuaHRtP3NfY2lkPW1tNjgwNmUxX3cpe3RhcmdldD0iX2JsYW5rIn0sIG92ZXJhbGwgdG9iYWNjbyB1c2UgKippbmNyZWFzZWQqKiBpbiB5b3V0aHMgKG1pZGRsZSBzY2hvb2xhbmQgaGlnaCBzY2hvb2wgc3R1ZGVudHMpIGluIHRoZSBVbml0ZWQgU3RhdGVzIGluIDIwMTcgYW5kIDIwMTgsIGRlc3BpdGUgcHJldmlvdXMgeWVhcnMgb2YgZGVjbGluaW5nIHVzZS4KClRoaXMgbWFqb3IgaW5jcmVhc2UgaXMgYXR0cmlidXRlZCB0byBhbiBpbmNyZWFzZSBpbiB0aGUgdXNlIG9mIGVsZWN0cm9uaWMgY2lnYWFyZXR0ZSAoZS1jaWdhcmV0dGUpIHByb2R1Y3RzLgoKRS1jaWdhcmV0dGVzIGFyZSByZWZlcnJlZCB0byBieSBtYW55IGRpZmZlcmVudCBuYW1lcywgaW5jbHVkaW5nIGJ1dCBub3QgbGltaXRlZCB0bzoKCjEpIEVsZWN0cm9uaWMgbmljb3RpbmUgZGVsaXZlcnkgc3lzdGVtcyAoRU5EUykKMikgVmFwZXMKMykgZS1ob29rYWhzCjQpIHZhcGUgcGVucwo1KSB0YW5rcwo2KSBtb2RzCgpUaGUgZGV2aWNlcyB2YXJ5IGdyZWF0bHk6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQoKaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cubHVuZy5vcmcvZ2V0bWVkaWEvOGFjOGFiOGMtZTdmYy00OTdiLTgzODQtNDQxNjE1ZjUwZmYwL2VjaWdzX0suanBnLmpwZyIpCmBgYAoKIyMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vd3d3Lmx1bmcub3JnL3F1aXQtc21va2luZy9lLWNpZ2FyZXR0ZXMtdmFwaW5nL2x1bmctaGVhbHRoKV0KClNlZSB0aGlzIFtDREMgZ3VpZGVdKGh0dHBzOi8vd3d3LmNkYy5nb3YvdG9iYWNjby9iYXNpY19pbmZvcm1hdGlvbi9lLWNpZ2FyZXR0ZXMvcGRmcy9lY2lnYXJldHRlLW9yLXZhcGluZy1wcm9kdWN0cy12aXN1YWwtZGljdGlvbmFyeS01MDgucGRmKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCB0aGUgW0FtZXJpY2FuIEx1bmcgQXNzb2NpYXRpb24gd2Vic2l0ZV0oaHR0cHM6Ly93d3cubHVuZy5vcmcvcXVpdC1zbW9raW5nL2UtY2lnYXJldHRlcy12YXBpbmcvbHVuZy1oZWFsdGgpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24uIAoKVGhlIHJlcG9ydCBmb3VuZCB0aGF0OgoKPiBEdXJpbmcgMjAxN+KAkzIwMTgsIGN1cnJlbnQgdXNlIG9mIGFueSB0b2JhY2NvIHByb2R1Y3QgKippbmNyZWFzZWQgMzguMyUqKiAoZnJvbSAxOS42JSB0byAyNy4xJSkgYW1vbmcgaGlnaCBzY2hvb2wgc3R1ZGVudHMgYW5kICoqMjguNiUqKiAoZnJvbSA1LjYlIHRvIDcuMiUpIGFtb25nIG1pZGRsZSBzY2hvb2wgc3R1ZGVudHM7IGUtY2lnYXJldHRlIHVzZSAqKmluY3JlYXNlZCA3Ny44JSoqIChmcm9tIDExLjclIHRvIDIwLjglKSBhbW9uZyBoaWdoIHNjaG9vbCBzdHVkZW50cyBhbmQgKio0OC41JSoqIChmcm9tIDMuMyUgdG8gNC45JSkgYW1vbmcgbWlkZGxlIHNjaG9vbCBzdHVkZW50cy4KCgpJbiAyMDE4LCB0aGUgW0ZlZGVyYWwgRHJ1ZyBBZG1pbmlzdHJhdGlvbiAoRkRBKSBpbiB0aGUgVW5pdGVkIFN0YXRlc10oaHR0cHM6Ly9hY3Nqb3VybmFscy5vbmxpbmVsaWJyYXJ5LndpbGV5LmNvbS9kb2kvZnVsbC8xMC4xMDAyL2NuY3IuMzE4Njgpe3RhcmdldD0iX2JsYW5rIn0gc3RhdGVkIHRoYXQgZS1jaWdhcmV0dGUgdXNhZ2UgdXNlIGFtb25nIHlvdXRoIHJlYWNoZWQ6ICAKCj4g4oCcbm90aGluZyBzaG9ydCBvZiBhbiAqKmVwaWRlbWljIHByb3BvcnRpb24gb2YgZ3Jvd3RoKirigJ0KCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgYmUgaW52aXN0aWdhdGluZyB0aGUgc2FtZSBkYXRhIHVzZWQgaW4gdGhlIHJlcG9ydCB0aGF0IGdlbmVyYXRlZCB0aGUgYWJvdmUgZmluZGluZ3MuIFRoaXMgZGF0YSBjb21lcyBmcm9tIHRoZSBbVGhlIE5hdGlvbmFsIFlvdXRoIFRvYmFjY28gU3VydmV5IChOWVRTKV0oaHR0cHM6Ly93d3cuY2RjLmdvdi90b2JhY2NvL2RhdGFfc3RhdGlzdGljcy9zdXJ2ZXlzL255dHMvaW5kZXguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9LgoKIyMjIyB7LnJlZmVyZW5jZV9ibG9ja30KCkdlbnR6a2UsIEFuZHJlYSBTLiwgTWVsaXNhIENyZWFtZXIsIEthcmVuIEEuIEN1bGxlbiwgQnJpZGdldCBLLiBBbWJyb3NlLCBHb3Jkb24gV2lsbGlzLCBBaG1lZCBKYW1hbCwgYW5kIEJyaWFuIEEuIEtpbmcuICDigJxWaXRhbCBTaWduczogVG9iYWNjbyBQcm9kdWN0IFVzZSBBbW9uZyBNaWRkbGUgYW5kIEhpZ2ggU2Nob29sIFN0dWRlbnRzIC0gVW5pdGVkIFN0YXRlcywgMjAxMS0yMDE4LuKAnSAqKk1NV1IuIE1vcmJpZGl0eSBhbmQgTW9ydGFsaXR5IFdlZWtseSBSZXBvcnQqKiA2OCAoNik6IDE1N+KAkzY0ICgyMDE5KS4KCiMjIyMKCgojIyAqKk1haW4gUXVlc3Rpb25zKioKKioqIAoKIyMjIyB7Lm1haW5fcXVlc3Rpb25fYmxvY2t9CjxiPjx1PiBPdXIgbWFpbiBxdWVzdGlvbjogPC91PjwvYj4KCjEpIEhvdyBoYXMgdG9iYWNjby9uaWNvdGluZSB1c2UgYnkgQW1lcmljYW4geW91dGhzIGNoYW5nZWQgc2luY2UgMjAxNT8gCjIpIEhvdyBkbyB2YXBpbmcgcmF0ZXMgY29tcGFyZSBiZXR3ZWVuIG1hbGVzIGFuZCBmZW1hbGVzPwozKSBXaGF0IHZhcGluZyBicmFuZHMgYW5kIGZsYXZvcnMgYXBwZWFyIHRvIGJlIHVzZWQgdGhlIG1vc3QgZnJlcXVlbnRseT8gIApXZSB3aWxsIGJhc2UgdGhpcyBvbiB0aGUgZm9sbG93aW5nIHN1cnZleSBxdWVzdGlvbnM6ICAgCj4gIkR1cmluZyB0aGUgcGFzdCAzMCBkYXlzLCB3aGF0IGJyYW5kIG9mIGUtY2lnYXJldHRlcyBkaWQgeW91IHVzdWFsbHkgdXNlPyIgICAKPiJXaGF0IGZsYXZvcnMgb2YgdG9iYWNjbyBwcm9kdWN0cyBoYXZlIHlvdSB1c2VkIGluIHRoZSBwYXN0CjMwIGRheXM/IiAgCgo0KSBIYXZlIHZhcGluZyByYXRlcyBwb3NzaWJseSBpbmZsdWVuY2VkIHRvYmFjY28vbmljb3RpbmUgdXNlPwoKIyMjIwoKCiMjICoqTGVhcm5pbmcgT2JqZWN0aXZlcyoqIAoqKiogCgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIHdpbGwgY292ZXIgaG93IHRvIGltcG9ydCBkYXRhIGZyb20gbXVsdGlwbGUgZmlsZXMgZWZmaWNpZW50bHksIGhvdyB0byBpbXBvcnQgZGF0YSBmcm9tIGV4Y2VsIGZpbGVzLCBhbmQgaG93IHRvIG1ha2UgYSB2YXJpZXR5IG9mIHZpc3VhbGl6YXRpb25zIHRvIGNvbXBhcmUgbXVsdGlwbGUgZ3JvdXBzIGFjcm9zcyB0aW1lLiBXZSB3aWxsIGFsc28gZGVtb25zdHJhdGUgaG93IHRvIHdvcmsgd2l0aCBjb2RlYm9va3MuIFdlIHdpbGwgY292ZXIgdGhlIGNvbmNlcHQgb2Ygc3VydmV5IHdlaWdodGluZyBhbmQgaW50cm9kdWNlIHRoZSBgc3J2eXJgIHBhY2thZ2UuIFdlIHdpbGwgZGlzY3VzcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHBvb2xlZCBjcm9zcy1zZWN0aW9uYWwgZGF0YSBhbmQgcGFuZWwgZGF0YS4gV2Ugd2lsbCBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW2BUaWR5dmVyc2VgXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSBmb3Igd3JhbmdsaW5nIGRhdGEsIHN1Y2ggYXMgYHRpZHlyYCBhbmQgYGRweXJgIGFuZCBmb3IgdmlzdWFsaXphdGlvbiwgc3VjaCBhcyBhcyBgZ2dwbG90MmAuIFRoZSB0aWR5dmVyc2UgaXMgYSBsaWJyYXJ5IG9mIHBhY2thZ2VzIGNyZWF0ZWQgYnkgUlN0dWRpby4gV2hpbGUgc29tZSBzdHVkZW50cyBtYXkgYmUgZmFtaWxpYXIgd2l0aCBwcmV2aW91cyBSIHByb2dyYW1taW5nIHBhY2thZ2VzLCB0aGVzZSBwYWNrYWdlcyBtYWtlIGRhdGEgc2NpZW5jZSBpbiBSIGVzcGVjaWFsbHkgZWZmaWNpZW50LgoKCmBgYHtyLCBvdXQud2lkdGggPSAiMjAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQoKaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly90aWR5dmVyc2UudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyIpCmBgYAoKCioqKiAKCgpXZSB3aWxsIGJlZ2luIGJ5IGxvYWRpbmcgdGhlIHBhY2thZ2VzIHRoYXQgd2Ugd2lsbCBuZWVkOgoKYGBge3J9CmxpYnJhcnkoaGVyZSkKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeSh0aWR5cikKbGlicmFyeShmb3JjYXRzKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KHN1bW1hcnl0b29scykKbGlicmFyeShzcnZ5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGNvd3Bsb3QpCmBgYAoKIFBhY2thZ2UgICB8IFVzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YSAgCltyZWFkeGxdKGh0dHBzOi8vcmVhZHhsLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBpbXBvcnQgdGhlIGRhdGEgaW4gdGhlIGV4Y2VsIGZpbGVzICAKW3B1cnJyXShodHRwczovL3B1cnJyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgfCB0byBpbXBvcnQgdGhlIGRhdGEgaW4gYWxsIHRoZSBkaWZmZXJlbnQgZXhjZWwgYW5kIGNzdiBmaWxlcyBlZmZpY2llbnRseQpbcmVhZHJdKGh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGltcG9ydCB0aGUgQ1NWIGZpbGUgZGF0YQpbZHBseXJdKGh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGFycmFuZ2UvZmlsdGVyL3NlbGVjdC9jb21wYXJlIHNwZWNpZmljIHN1YnNldHMgb2YgdGhlIGRhdGEgIApbc3VtbWFyeXRvb2xzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvc2tpbXIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gZ2V0IGFuIG92ZXJ2aWV3IG9mIGRhdGEgaW4gYSBkaWZmZXJlbnQgc3R5bGUgICAKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byByZWFycmFuZ2UgZGF0YSBpbiB3aWRlIGFuZCBsb25nIGZvcm1hdHMgCgoKW3N0cmluZ3JdKGh0dHBzOi8vc3RyaW5nci50aWR5dmVyc2Uub3JnL2FydGljbGVzL3N0cmluZ3IuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIG1hbmlwdWxhdGUgdGhlIGNoYXJhY3RlciBzdHJpbmdzIHdpdGhpbiB0aGUgZGF0YSAgIApbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIHwgdG8gbWFrZSB2aXN1YWxpemF0aW9ucyB3aXRoIG11bHRpcGxlIGxheWVycyAgCltnZ3B1YnJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9nZ3B1YnIvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICB8IHRvIGVhc2lseSBhZGQgcmVncmVzc2lvbiBsaW5lIGVxdWF0aW9ucyB0byBwbG90cyAgCltmb3JjYXRzXShodHRwczovL2ZvcmNhdHMudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgfCB0byBjaGFuZ2UgZGV0YWlscyBhYm91dCBmYWN0b3JzIChjYXRlZ29yaWNhbCB2YXJpYWJsZXMpICAKW2xtZXJUZXN0XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbG1lclRlc3QvbG1lclRlc3QucGRmKXwgdG8gcGVyZm9ybSBsaW5lYXIgbWl4ZWQgbW9kZWwgdGVzdGluZyAgIApbY2FyXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY2FyL2Nhci5wZGYpfCB0byBwZXJmb3JtIExldmVuZSdzIFRlc3Qgb2YgSG9tb2dlbmVpdHkgb2YgVmFyaWFuY2VzICAgCltnZ2lyYXBoXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2dpcmFwaC9pbmRleC5odG1sKXwgdG8gbWFrZSBwbG90cyBpbnRlcmFjdGl2ZSAgIApbZ2dmb3JjZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2dnZm9yY2UvZ2dmb3JjZS5wZGYpfCB0byBtb2RpZnkgZmFjZXRzIGluIHBsb3RzICAKW3ZpcmlkaXNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy92aXJpZGlzL3ZpZ25ldHRlcy9pbnRyby10by12aXJpZGlzLmh0bWwpfCB0byBwbG90IGluIGNvbG9yIHBhbGV0dGUgICAgCltjb3dwbG90XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY293cGxvdC92aWduZXR0ZXMvaW50cm9kdWN0aW9uLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gfCB0byBhbGxvdyBwbG90cyB0byBiZSBjb21iaW5lZCAgIFtza2ltcl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3NraW1yL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGdldCBhbiBvdmVydmlldyBvZiBkYXRhICAgCgoKCgpUaGUgZmlyc3QgdGltZSB3ZSB1c2UgYSBmdW5jdGlvbiwgd2Ugd2lsbCB1c2UgdGhlIGA6OmAgdG8gaW5kaWNhdGUgd2hpY2ggcGFja2FnZSB3ZSBhcmUgdXNpbmcuIFVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBiZSBpbmZvcm1hdGl2ZSBhYm91dCB3aGVyZSB0aGUgZnVuY3Rpb25zIHdlIHdpbGwgdXNlIGNvbWUgZnJvbS4KCgojIyAqKkNvbnRleHQqKgoqKiogCgpBY2NvcmRpbmcgdG8gdGhlIGNpdGVkIFtNb3JiaWRpdHkgYW5kIE1vcnRhbGl0eSBXZWVrbHkgUmVwb3J0XShodHRwczovL3d3dy5jZGMuZ292L21td3Ivdm9sdW1lcy82OC93ci9tbTY4MDZlMS5odG0/c19jaWQ9bW02ODA2ZTFfdykgdGhpcyB3YXMgd2hhdCB3YXMgYWxyZWFkeSBrbm93biBhYm91dCB0aGlzIHRvcGljIGFuZCB0aGUgaW1wbGljYXRpb25zIG9mIHRoaXMgc3R1ZHk6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiODAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJjb250ZXh0LnBuZyIpKQoKYGBgCgoKSW1wb3J0YW50bHksIHRoZSB2YXBvcnMgdXNlZCBpbiBlLWNpZ2FyZXR0ZXMgY29udGFpbiBoYXJtZnVsIGNoZW1pY2FsczoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CgppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3d3dy5jZGMuZ292L3RvYmFjY28vYmFzaWNfaW5mb3JtYXRpb24vZS1jaWdhcmV0dGVzL2ltYWdlcy9lLWNpZ2FyZXR0ZS1hZXJvc29sLWNhbi1jb250YWluLWhhcm1mdWwtaW5ncmVkaWVudHMtZGVza3RvcC03MDAuanBnIikKYGBgCgpFLWNpZ2FyZXR0ZSB1c2FnZSBoYXMgYWxzbyBiZWVuIGFzc29jaWF0ZWQgd2l0aCBbbHVuZyBpbmp1cnldKChodHRwczovL3d3dy5mcm9udGllcnNpbi5vcmcvYXJ0aWNsZXMvMTAuMzM4OS9mcGhhci4yMDE5LjAxNjE5L2Z1bGwpKXt0YXJnZXQ9Il9ibGFuayJ9CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiODAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJsdW5nLnBuZyIpKQpgYGAKClNlZSBbaGVyZV0oaHR0cHM6Ly93d3cuY2RjLmdvdi90b2JhY2NvL2Jhc2ljX2luZm9ybWF0aW9uL2UtY2lnYXJldHRlcy9RdWljay1GYWN0cy1vbi10aGUtUmlza3Mtb2YtRS1jaWdhcmV0dGVzLWZvci1LaWRzLVRlZW5zLWFuZC1Zb3VuZy1BZHVsdHMuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgYWRkaXRvbmFsIGluZm9ybWF0aW9uIGFib3V0IHRoZSBwb3RlbnRpYWwgaGVhbHRoIGVmZmVjdHMgb2YgZS1jaWdhcmV0dGVzIGluIHRlZW5zIGFuZCB5b3VuZyBhZHVsdHMuCgojIyAqKkxpbWl0YXRpb25zKioKKioqIApUaGVyZSBhcmUgc29tZSBpbXBvcnRhbnQgY29uc2lkZXJhdGlvbnMgcmVnYXJkaW5nIHRoaXMgZGF0YSBhbmFseXNpcyB0byBrZWVwIGluIG1pbmQ6IAoKQVZPQ0FETy4uTmVlZCBNaWNoYWVsIHRvIGxvb2sgYXQgdGhlc2UuLi4KCjEpIFRoZSBkYXRhIGluY2x1ZGVkIGluIHRoZSBbTmF0aW9uYWwgWW91dGggVG9iYWNjbyBTdXJ2ZXkgKE5ZVFMpXShodHRwczovL3d3dy5jZGMuZ292L3RvYmFjY28vZGF0YV9zdGF0aXN0aWNzL3N1cnZleXMvbnl0cy9pbmRleC5odG0pe3RhcmdldD0iX2JsYW5rIn0gZG9lcyBub3QgZm9sbG93IHRoZSBzYW1lIGluZGl2aWR1YWwgc3R1ZGVudHMgb3ZlciB0aW1lLiAgQSBbbG9uZ2l0dWRpbmFsIHN0dWR5XShodHRwczovL3d3dy5ibWouY29tL2Fib3V0LWJtai9yZXNvdXJjZXMtcmVhZGVycy9wdWJsaWNhdGlvbnMvZXBpZGVtaW9sb2d5LXVuaW5pdGlhdGVkLzctbG9uZ2l0dWRpbmFsLXN0dWRpZXMpe3RhcmdldD0iX2JsYW5rIn0gdGhhdCBkb2VzIGZvbGxvdyB0aGUgc2FtZSBpbmRpdmlkdWFscyBvdmVyIHRpbWUgY29sbGVjdHMgZGF0YSBjYWxsZWQgW3BhbmVsIGRhdGFdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BhbmVsX2RhdGEpLiBUaGUgZGF0YSBpbiB0aGlzIHN0dWR5IGlzIGNhbGxlZCBwb29sZWQgW2Nyb3NzLXNlY3Rpb25hbCBkYXRhXWh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Nyb3NzLXNlY3Rpb25hbF9kYXRhLCB0aGlzIGRhdGEgaXMgb2J0YWluZWQgZnJvbSByYW5kb20gY29sbGVjdGlvbiBvZiBvYmVydmF0aW9ucyBhY3Jvc3MgdGltZS4KCkFjY29yZGluZyB0byB3aWtpcGVkaWE6Cj5QYW5lbCBkYXRhIGRpZmZlcnMgZnJvbSBwb29sZWQgY3Jvc3Mtc2VjdGlvbmFsIGRhdGEgYWNyb3NzIHRpbWUsIGJlY2F1c2UgaXQgZGVhbHMgd2l0aCB0aGUgb2JzZXJ2YXRpb25zIG9uIHRoZSBzYW1lIHN1YmplY3RzIGluIGRpZmZlcmVudCB0aW1lcyB3aGVyZWFzIHRoZSBsYXR0ZXIgb2JzZXJ2ZXMgZGlmZmVyZW50IHN1YmplY3RzIGluIGRpZmZlcmVudCB0aW1lIHBlcmlvZHMKCgpBVk9DQURPIHJldmlzaXQgdGhpcy4uLgoyKSBUaGUgZGF0YSBhbHNvIGluY2x1ZGVzIHBlcmNlbnRhZ2VzIG9mIHN0dWRlbnRzIHRoYXQgcmVwb3J0ZWQgdXNlIG9mIHBhcnRpY3VsYXIgdG9iYWNjbyBwcm9kdWN0LCBidXQgdGhlIHN1cnZleSBxdWVzdGlvbnMgZGlkIG5vdCBhc2sgIGhvdyBtdWNoIHVzZXMgb2Ygb25lIHByb2R1Y3QgY29tcGFyZWQgdG8gYW5vdGhlciAtIGZvciBleGFtcGxlIG1lbnRob2wgZmxhdm9yZWQgcHJvZHVjdHMgd2hlcmUgdXNlZCBhdCB0aGUgbmVhciBleGNsdXNpb24gb2Ygb3RoZXIgZmxhdm9ycy4gCgpXaGlsZSBbZ2VuZGVyXShodHRwczovL3d3dy5nZW5kZXJzcGVjdHJ1bS5vcmcvcXVpY2stbGlua3MvdW5kZXJzdGFuZGluZy1nZW5kZXIvKXt0YXJnZXQ9Il9ibGFuayJ9IGFuZCBbc2V4XShodHRwczovL3d3dy53aG8uaW50L2dlbm9taWNzL2dlbmRlci9lbi9pbmRleDEuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBhcmUgbm90IGFjdHVhbGx5IGJpbmFyeSwgdGhlIGRhdGEgIHVzZWQgaW4gdGhpcyBhbmFseXNpcyBvbmx5IGNvbnRhaW5zIGluZm9ybWF0aW9uIGZvciBncm91cHMgb2YgaW5kaXZpZHVhbHMgd2hvIGFuc3dlcmVkIHRoZSBzdXJ2ZXkgcXVlc3Rpb25zIGFzIG1hbGUgb3IgZmVtYWxlLiAKCgpBVk9DQURPLi4gc2hvdWxkIHdlIGRyb3AgdGhlIHJhY2UgZGF0YT8gd2UgZGlkbnQgdXNlIGl0Li4uCkZ1cnRoZXJtb3JlLCB3aGlsZSB0aGUgcmFjZSBvZiBpbmRpdmlkdWFsIHN0dWRlbnRzIHdhcyBzdXJ2ZXllZCBhbmQgYXNrZWQgc3R1ZGVudHMgdG8gc2VsZiByZXBvcnQgYmFzZWQgb24gd2hhdCByYWNlIG9yIHJhY2VzIHRoZXkgY29uc2lkZXJlZCB0aGVtc2VsdmVzIHRvIGJlLCB0aGlzIGxpc3Qgb25seSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nIG9wdGlvbnM6ICAgIAoxKSBIaXNwYW5pYywgTGF0aW5vLCBMYXRpbmEsIG9yIFNwYW5pc2ggb3JpZ2luIGFzIG9uZSBzaW5nbGUgcmFjZSB3aXRoIHRoZSBmb2xsb3dpbmcgZnVydGhlciBvcHRpb25zOiAgCiAgICAxKSBNZXhpY2FuLCBNZXhpY2FuIEFtZXJpY2FuLCBDaGljYW5vLCBvciBDaGljYW5hICAKICAgIDIpIFB1ZXJ0byBSaWNhbiAgCiAgICAzKSBDdWJhbiAgCiAgICA0KSBZZXMsIEFub3RoZXIgSGlzcGFuaWMsIExhdGlubywgTGF0aW5hLCBvciBTcGFuaXNoIG9yaWdpbiAgCjIpCgoKIyMgKipXaGF0IGFyZSB0aGUgZGF0YT8qKgoqKiogCiAKVGhlIGRhdGEgaW4gdGhpcyBjYXNlIHN0dWR5IGNvbWVzIGZyb20gdGhlIFtOYXRpb25hbCBZb3V0aCBUb2JhY2NvIFN1cnZleSAoTllUUyldKGh0dHBzOi8vd3d3LmNkYy5nb3YvdG9iYWNjby9kYXRhX3N0YXRpc3RpY3Mvc3VydmV5cy9ueXRzL2luZGV4Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifSB3aGljaCBpcyBhbiBhbm51YWwgc3VydmV5IHRoYXQgYXNrcyBzdHVkZW50cyAgaW4gaGlnaCBzY2hvb2wgYW5kIG1pZGRsZSBzY2hvb2wgKGdyYWRlcyA2LTEyKSBhYm91dCB0b2JhY2NvIHVzYWdlIGluIHRoZSBVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EuCgpUaGUgZGF0YSBmb3IgdGhpcyBzdXJ2ZXkgaXMgZnJlZWx5IGF2YWlsYWJsZSBvbmxpbmUgYXQgdGhpcyBbd2Vic2l0ZV0oaHR0cHM6Ly93d3cuY2RjLmdvdi90b2JhY2NvL2RhdGFfc3RhdGlzdGljcy9zdXJ2ZXlzL255dHMvZGF0YS9pbmRleC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHdpdGggZGF0YSBmcm9tIDE5OTksIDIwMDAsIDIwMDIsIDIwMDQsIDIwMDYsIDIwMDksICBhbmQgMjAxMS0yMDE5LiBXZSB3aWxsIGJlIHVzaW5nIGRhdGEgZnJvbSAqKjIwMTUtMjAxOSoqIGR1ZSB0byB0aGUgZmFjdCB0aGF0IHRoZXNlIHllYXJzIGFyZSB0aGUgbW9zdCByZWNlbnQgdGhhdCBhc2tlZCBxdWVzdGlvbnMgcmVjYXJkaW5nIGUtY2lnYXJldHRlIHVzYWdlLgoKRWFjaCB5ZWFyIGluY2x1ZGVzIGRvY3VtZW50YXRpb24sIHN1Y2ggYXMgYSBbY29kZWJvb2tdKGh0dHBzOi8vd3d3LmljcHNyLnVtaWNoLmVkdS9pY3BzcndlYi9jb250ZW50L3NoYXJlZC9JQ1BTUi9mYXFzL3doYXQtaXMtYS1jb2RlYm9vay5odG1sKSBhbmQgYW4gZXhjZWwgZmlsZSBjb250YWluaW5nIHRoZSBkYXRhOgoKYGBge3IsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIiwgb3V0LndpZHRoID0gIjYwMCBweCJ9Cgprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiZGF0YS5wbmciKSkKYGBgClRoZXJlZm9yZSwgc2luY2Ugd2UgYXJlIHVzaW5nIGRhdGEgZnJvbSAqKjIwMTUtMjAxOSoqLCB0aGUgZGF0YSB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBpcyBsb2NhdGVkIGluIDUgZGlmZmVyZW50IGV4Y2VsIGZpbGVzLCBlYWNoIHdpdGggdGhlaXIgb3duIFtjb2RlYm9va10oaHR0cHM6Ly93d3cuaWNwc3IudW1pY2guZWR1L2ljcHNyd2ViL2NvbnRlbnQvc2hhcmVkL0lDUFNSL2ZhcXMvd2hhdC1pcy1hLWNvZGVib29rLmh0bWwpLgoKVGhlIFtjb2RlYm9va10oaHR0cHM6Ly93d3cuaWNwc3IudW1pY2guZWR1L2ljcHNyd2ViL2NvbnRlbnQvc2hhcmVkL0lDUFNSL2ZhcXMvd2hhdC1pcy1hLWNvZGVib29rLmh0bWwpIGNvbnRhaW5zIGluZm9ybWF0aW9uIGRlc2NyaWJpbmcgdGhlIGRhdGEgd2l0aGluIHRoZSBleGNlbCBmaWxlLiAKCkFzIHlvdSBjYW4gc2VlIHRoZSBleGNlbCBmaWxlIGNvbnRhaW5zIHZlcnkgc2hvcnQgdmFyaWFibGUgbmFtZXMgYW5kIHZhbHVlcywgYW5kIGl0IGlzIG5vdCBjbGVhciB3aGF0IHRoZXkgbWVhbiB3aXRob3V0IHRoZSBjb2RlYm9vazoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciIsIG91dC53aWR0aCA9ICI2MDAgcHgifQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgImV4Y2VsLnBuZyIpKQpgYGAKClRoZSBjb2RlYm9vayBleHBsYWlucyB3aGF0IHRoZSB2YXJpYWJsZXMgKHRoZSBjb2x1bW5zKSBhcmU6CmBgYHtyLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciIsIG91dC53aWR0aCA9ICI2MDAgcHgifQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInZhcmlhYmxlcy5wbmciKSkKYGBgCgpBbmQgdGhlIGNvZGVib29rIGV4cGxhaW5zIHdoYXQgdGhlIHZhbHVlcyBmb3IgZWFjaCB2YXJpYWJsZSBhcmU6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIiLCBvdXQud2lkdGggPSAiNjAwIHB4In0KCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJxbjEucG5nIikpCmBgYAoKV2Ugd2lsbCBleHBsYWluIG1vcmUgbGF0ZXIgYWJvdXQgd2hhdCB0aGUgdmFsdWVzIG9uIHRoZSByaWdodCBpbmRpY2F0ZS4KClRoZSByZWFzb24gdGhhdCB0aGVyZSBhcmUgY29kZWJvb2tzIGZvciBlYWNoIHllYXIgaXMgYmVjYXVzZSB0aGUgcXVlc3Rpb25zIGFza2VkIHllYXIgdmFyaWVkIHNsaWdodGx5LgoKClRoZSBkYXRhIGluIHRoaXMgc3VydmV5IGlzIHdoYXQgaXMgY2FsbGVkIHBvb2xlZCBjcm9zcy1zZWN0aW9uYWwgZGF0YS4gSW4gb3RoZXJ3b3JkcywgZGlmZmVyZW50IHN1YnNldHMgb2Ygc3R1ZGVudHMgYXJlIHN1cnZleWVkIGVhY2ggeWVhciBhbmQgaXQgaXMgbm90IGNsZWFyIHdoaWNoLCBpZiBhbnkgLCBpbmRpdmlkdWFscyBwYXJ0aWNwYXRlIGZyb20gb25lIHllYXIgdG8gdGhlIG5leHQuCgojIyAqKkRhdGEgSW1wb3J0KioKKioqIApTaW5jZSB0aGVzZSBleGNlbCBmaWxlcyBhcmUgc28gbGFyZ2UsIGl0IHRha2VzIGEgYml0IG9mIHRpbWUgZm9yIHRoZSBkYXRhIHRvIGxvYWQuIFRvIG1ha2UgdGhlIHByb2Nlc3MgZmFzdGVyLCB3ZSBwcmV2aW91c2x5IGltcG9ydGVkIHRoZXNlIGZpbGVzLCBzZWxlY3RlZCBvbmx5IG91ciBxdWVzdGlvbnMgb2YgaW50ZXJlc3QsIGFuZCBzYXZlZCB0aGlzIGRhdGEgYXMgY3N2IGZpbGVzLiAKCkFWT0NBRE8gc2hvdWxkIHdlIGRyb3AgdGhlIHJhY2UgZGF0YT8gd2UgZGlkbid0IGVuZCB1cCBkb2luZyBhbnl0aGluZyB3aXRoIHRoaXMuLi4uCgo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSBmb3IgZGV0YWlscyBvbiBob3cgdGhlIGRhdGEgd2FzIG9yaWdpbmFsbHkgaW1wb3J0ZWQgPC9zdW1tYXJ5PgoKRmlyc3Qgd2UgY3JlYXRlZCBhIGxpc3Qgb2YgZmlsZW5hbWVzIG9mIGFsbCB0aGUgZGlmZmVyZW50IGV4Y2VsIGZpbGVzLiBVc2luZyB0aGUgYGhlcmUoKWAgZnVuY3Rpb24gb2YgdGhlIGBoZXJlYCBwYWNrYWdlLCB3ZSBsb29rZWQgaW4gYWxsIHRoZSBkaXJlY3RvcmllcyBvZiB0aGUgcHJvamVjdC4KVGhlIGBsaXN0LmZpbGVzKClgIGZ1bmN0aW9uIGxvb2tlZCBmb3IgYWxsIGZpbGVzIHdpdGggLnhsc3ggd2l0aGluIHRoZXNlIHN1YmRpcmVjdG9yaWVzLgpgYGB7cn0KZXhjZWxfZmlsZXM8LWxpc3QuZmlsZXMoaGVyZTo6aGVyZSgpLCByZWN1cnNpdmUgPSBUUlVFLAogICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIioueGxzeCIpCmV4Y2VsX2ZpbGVzCmBgYAoKQWxsIHRoZSBmaWxlcyB3ZXJlIHJlYWQgdXNpbmcgcmVhZF9leGNlbCBvZiB0aGUgcmVhZHhsIHBhY2thZ2UuVXNpbmcgdGhlIG1hcCgpIGZ1bmN0aW9uIG9mIHRoZSBwdXJyciBwYWNrYWdlIHRoaXMgd2FzIGRvbmUgZWZmaWNpZW50bHkuClRoaXMgY3JlYXRlZCBhIHNpbmdsZSBsaXN0IG9mIHRpYmJsZXMgKG9uZSBmb3IgZWFjaCBmaWxlKS4gCmBgYHtyLCBldmFsID0gRkFMU0V9CnRibCA8LSBleGNlbF9maWxlcyAlPiUgCiAgICAgICBtYXAofnJlYWR4bDo6cmVhZF9leGNlbCguKSkKYGBgCgpFYWNoIGV4Y2VsIGZpbGUgbmFtZSB3YXMgZXh0cmFjdGVkIHVzaW5nIHRoZSBzdHJfZXh0cmFjdCgpIGZ1bmN0aW9uIG9mIHRoZSBzdHJpbmdyIHBhY2thZ2UuCmBgYHtyfQp0YmxfbmFtZXMgPC0gZXhjZWxfZmlsZXMgJT4lCiAgc3RyX2V4dHJhY3QoIm55dHNbMl1bMF1bMV1bNS05XSIpCnRibF9uYW1lcwpgYGAKClRoZXNlIG5hbWVzIGJlY2FtZSB0aGUgbmFtZXMgb2YgdGhlIHRpYmJsZXMgaW4gdGhlIGxpc3Qgb2YgdGliYmxlcy4KYGBge3IsIGV2YWwgPSBGQUxTRX0KbmFtZXModGJsKSA8LSB0YmxfbmFtZXMKYGBgCgoKU3BlY2lmaWMgY29sdW1ucyB3ZXJlIHNlbGVjdGVkIGZyb20gZWFjaCBvZiB0aGUgdGliYmxlcyB1c2luZyB0aGUgdmFyYWlibGUgbmFtZSwgYXMgaWRlbnRpZmllZCBpbiB0aGUgY29kZWJvb2sgZm9yIGJlaW5nIG9mIGludGVyZXN0LgpJbiBzb21lIGNhc2VzIGZ1bmN0aW9ucyBsaWtlIHN0YXJ0c193aXRoKCkgb2YgdGhlIGRwbHlyIHBhY2thZ2Ugd2VyZSB1c2VkIHRvIHNlbGVjdCBzZXZlcmFsIHZhcmlhYmxlcy4KCmBgYHtyLCBldmFsID0gRkFMU0V9Cgp0YmxbWyJueXRzMjAxNSJdXSA8LSB0YmxbWyJueXRzMjAxNSJdXSAlPiUKICAgIGRwbHlyOjpzZWxlY3QocHN1LAogICAgICAgICAgICAgICAgICBmaW53Z3QsCiAgICAgICAgICAgICAgICAgIHN0cmF0dW0sCiAgICAgICAgICAgICAgICAgIFFuMSwgI0FnZQogICAgICAgICAgICAgICAgICBRbjIsICNTZXgKICAgICAgICAgICAgICAgICAgUW4zLCAjR3JhZGUKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlFuNCIpLCAjSGlzcGFuaWMvTGF0aW5vCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJRbjUiKSwgI1JhY2UsCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJFIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIEVGTEFWQ0lHVFMsCiAgICAgICAgICAgICAgICAgIENGTEFWQ0lHVFMsCiAgICAgICAgICAgICAgICAgIEVGTEFWQ0lHQVIsCiAgICAgICAgICAgICAgICAgICkKCnRibFtbIm55dHMyMDE2Il1dIDwtIHRibFtbIm55dHMyMDE2Il1dICU+JQogICAgZHBseXI6OnNlbGVjdChwc3UsCiAgICAgICAgICAgICAgICAgIGZpbndndCwKICAgICAgICAgICAgICAgICAgc3RyYXR1bSwKICAgICAgICAgICAgICAgICAgUTEsICNBZ2UKICAgICAgICAgICAgICAgICAgUTIsICNTZXgKICAgICAgICAgICAgICAgICAgUTMsICNHcmFkZQogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTQiKSwgI0hpc3BhbmljL0xhdGlubwogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTUiKSwgI1JhY2UKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgRUZMQVZDSUdBUiwKICAgICAgICAgICAgICAgICAgUTUwQSwgI01lbnRob2wgIyBXaGF0IGZsYXZvcnMgb2YgdG9iYWNjbyBwcm9kdWN0cyBoYXZlIHlvdSB1c2VkIGluIHRoZSBwYXN0IDMwIGRheXM/IChTZWxlY3Qgb25lIG9yIG1vcmUpCiAgICAgICAgICAgICAgICAgIFE1MEIsICNDbG92ZSBvciBzcGljZQogICAgICAgICAgICAgICAgICBRNTBDLCAjRnJ1aXQKICAgICAgICAgICAgICAgICAgUTUwRCwgI0Nob2NvbGF0ZQogICAgICAgICAgICAgICAgICBRNTBFLCAjQWxjb2hvbGljIERyaW5rCiAgICAgICAgICAgICAgICAgIFE1MEYsICNDYW5keS9EZXNzZXJ0cy9PdGhlciBTd2VldHMKICAgICAgICAgICAgICAgICAgUTUwRywgI1NvbWUgT3RoZXIgRmxhdm9yIE5vdCBMaXN0ZWQgSGVyZQogICAgICAgICAgICAgICAgICBRNTBIICNJIERpZCBOb3QgVXNlIEZsYXZvcmVkIFRvYmFjY28gUHJvZHVjdHMgSW4gdGhlIFBhc3QKICAgICAgICAgICAgICAgICAgKSAKCnRibFtbIm55dHMyMDE3Il1dIDwtIHRibFtbIm55dHMyMDE3Il1dICU+JQogICAgZHBseXI6OnNlbGVjdChwc3UsCiAgICAgICAgICAgICAgICAgIGZpbndndCwKICAgICAgICAgICAgICAgICAgc3RyYXR1bSwKICAgICAgICAgICAgICAgICAgUTEsICNBZ2UKICAgICAgICAgICAgICAgICAgUTIsICNTZXgKICAgICAgICAgICAgICAgICAgUTMsICNHcmFkZQogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTQiKSwgI0hpc3BhbmljL0xhdGlubwogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTUiKSwgI1JhY2UKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgQ0JJRElTLAogICAgICAgICAgICAgICAgICBRNTBBLCAjTWVudGhvbCAjIFdoYXQgZmxhdm9ycyBvZiB0b2JhY2NvIHByb2R1Y3RzIGhhdmUgeW91IHVzZWQgaW4gdGhlIHBhc3QgMzAgZGF5cz8gKFNlbGVjdCBvbmUgb3IgbW9yZSkKICAgICAgICAgICAgICAgICAgUTUwQiwgI0Nsb3ZlIG9yIHNwaWNlCiAgICAgICAgICAgICAgICAgIFE1MEMsICNGcnVpdAogICAgICAgICAgICAgICAgICBRNTBELCAjQ2hvY29sYXRlCiAgICAgICAgICAgICAgICAgIFE1MEUsICNBbGNvaG9saWMgRHJpbmsKICAgICAgICAgICAgICAgICAgUTUwRiwgI0NhbmR5L0Rlc3NlcnRzL090aGVyIFN3ZWV0cwogICAgICAgICAgICAgICAgICBRNTBHLCAjU29tZSBPdGhlciBGbGF2b3IgTm90IExpc3RlZCBIZXJlCiAgICAgICAgICAgICAgICAgIFE1MEggI0kgRGlkIE5vdCBVc2UgRmxhdm9yZWQgVG9iYWNjbyBQcm9kdWN0cyBJbiB0aGUgUGFzdAogICAgICAgICAgICAgICAgICApCgp0YmxbWyJueXRzMjAxOCJdXSA8LSB0YmxbWyJueXRzMjAxOCJdXSAlPiUKICAgIGRwbHlyOjpzZWxlY3QocHN1LAogICAgICAgICAgICAgICAgICBmaW53Z3QsCiAgICAgICAgICAgICAgICAgIHN0cmF0dW0sCiAgICAgICAgICAgICAgICAgIFExLCAjQWdlCiAgICAgICAgICAgICAgICAgIFEyLCAjU2V4CiAgICAgICAgICAgICAgICAgIFEzLCAjR3JhZGUKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlE0IiksICNIaXNwYW5pYy9MYXRpbm8KICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlE1IiksICNSYWNlCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJFIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIFE1MEEsICNNZW50aG9sICMgV2hhdCBmbGF2b3JzIG9mIHRvYmFjY28gcHJvZHVjdHMgaGF2ZSB5b3UgdXNlZCBpbiB0aGUgcGFzdCAzMCBkYXlzPyAoU2VsZWN0IG9uZSBvciBtb3JlKQogICAgICAgICAgICAgICAgICBRNTBCLCAjQ2xvdmUgb3Igc3BpY2UKICAgICAgICAgICAgICAgICAgUTUwQywgI0ZydWl0CiAgICAgICAgICAgICAgICAgIFE1MEQsICNDaG9jb2xhdGUKICAgICAgICAgICAgICAgICAgUTUwRSwgI0FsY29ob2xpYyBEcmluawogICAgICAgICAgICAgICAgICBRNTBGLCAjQ2FuZHkvRGVzc2VydHMvT3RoZXIgU3dlZXRzCiAgICAgICAgICAgICAgICAgIFE1MEcsICNTb21lIE90aGVyIEZsYXZvciBOb3QgTGlzdGVkIEhlcmUKICAgICAgICAgICAgICAgICAgUTUwSCAjSSBEaWQgTm90IFVzZSBGbGF2b3JlZCBUb2JhY2NvIFByb2R1Y3RzIEluIHRoZSBQYXN0CiAgICAgICAgICAgICAgICAgICkKCnRibFtbIm55dHMyMDE5Il1dIDwtIHRibFtbIm55dHMyMDE5Il1dICU+JQogICAgZHBseXI6OnNlbGVjdChwc3UsCiAgICAgICAgICAgICAgICAgIGZpbndndCwKICAgICAgICAgICAgICAgICAgc3RyYXR1bSwKICAgICAgICAgICAgICAgICAgUTEsICNBZ2UKICAgICAgICAgICAgICAgICAgUTIsICNTZXgKICAgICAgICAgICAgICAgICAgUTMsICNHcmFkZQogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTQiKSwgI0hpc3BhbmljL0xhdGlubwogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiUTUiKSwgI1JhY2UKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgRUhUUCwKICAgICAgICAgICAgICAgICAgQ0hUUCwKICAgICAgICAgICAgICAgICAgUTQwLCAjQnJhbmcsIGUtY2lnYXJldHRlcwogICAgICAgICAgICAgICAgICBRNjJBLCAjTWVudGhvbCAjIFdoYXQgZmxhdm9ycyBvZiB0b2JhY2NvIHByb2R1Y3RzIGhhdmUgeW91IHVzZWQgaW4gdGhlIHBhc3QgMzAgZGF5cz8gKFNlbGVjdCBvbmUgb3IgbW9yZSkKICAgICAgICAgICAgICAgICAgUTYyQiwgI0Nsb3ZlIG9yIHNwaWNlCiAgICAgICAgICAgICAgICAgIFE2MkMsICNGcnVpdCAKICAgICAgICAgICAgICAgICAgUTYyRCwgI0Nob2NvbGF0ZQogICAgICAgICAgICAgICAgICBRNjJFLCAjQWxjb2hvbGljIERyaW5rCiAgICAgICAgICAgICAgICAgIFE2MkYsICNDYW5keS9EZXNzZXJ0cy9PdGhlciBTd2VldHMKICAgICAgICAgICAgICAgICAgUTYyRywgI1NvbWUgT3RoZXIgRmxhdm9yIE5vdCBMaXN0ZWQgSGVyZSAKICAgICAgICAgICAgICAgICAgKQpgYGAKCkEgZGlyZWN0b3J5IHdhcyBjcmVhdGVkIHVzaW5nIHRoZSBiYXNlIGBkaXIuY3JlYXRlKClgIGZ1bmN0aW9uIGNhbGxlZCBgZGF0YV9yZWR1Y2VkYCBmb3IgdGhlIGNzdiBmaWxlcy4gCk5ldyBjc3YgZmlsZXMgd2VyZSBjcmVhdGVkIGZvciBlYWNoIG9mIHRoZSB0YmxzIGluIHRoZSBsaXN0IHVzaW5nIHRoZSBgd3JpdGVfY3N2KClgIGZ1bmN0aW9uIG9mIHRoZSBgcmVhZHJgIHBhY2thZ2UuClRoaXMgd2FzIGRvbmUgYWxsIGF0IG9uY2UgdXNpbmcgdGhlIGJhc2UgYG1hcHB5KClgIGZ1bmN0aW9uLgoKYGBge3IsIGV2YWwgPSBGQUxTRX0KIyAKZGlyLmNyZWF0ZSgiZG9jcy9kYXRhX3JlZHVjZWQiKQoKbWFwcGx5KHdyaXRlX2NzdiwgdGJsLCBwYXRoPWhlcmUocGFzdGUwKCJkb2NzL2RhdGFfcmVkdWNlZC8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXModGJsKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnLmNzdicpKQogICAgICkKIyB0YmwgJT4lCiMgICBuYW1lcyguKSAlPiUKIyBtYXAofndyaXRlX2Nzdih0aWJibGUoLikgLCBwYXRoPXBhc3RlMCgiZG9jcy9kYXRhX3JlZHVjZWQyLyIsLiwgIi5jc3YiKSkpCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIApgYGAKCjwvZGV0YWlscz4KCgoKTm93IHdlIHdpbGwgc2hvdyBob3cgdG8gcmVhZCBpbiB0aGUgZGF0YSBmcm9tIHRoZSBmaXZlIENTViBmaWxlcyB0aGF0IHdlcmUgY3JlYXRlZCBmcm9tIHRoZSBmaXZlIGRpZmZlcmVudCBleGNlbCBmaWxlcy4KCiMjIyBSZWFkaW5nIGluIHRoZSBDU1YgZmlsZXMKCmBgYHtyLCBlY2hvPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpzdGFydF90aW1lIDwtIFN5cy50aW1lKCkKCmVuZF90aW1lIDwtIFN5cy50aW1lKCkKCnRlc3RfdGltZSA8LSBlbmRfdGltZSAtIHN0YXJ0X3RpbWUKCnRpbWVfbWVzc2FnZSA8LSBwYXN0ZSgiRHVyYXRpb24gb2YgZGF0YSBpbXBvcnQ6IiwKICAgICAgcm91bmQoYXMubnVtZXJpYyh0ZXN0X3RpbWUpICwzKSwKICAgICAgdW5pdHModGVzdF90aW1lKQogICAgICApCmBgYAoKCmBgYHtyfQpjc3ZzIDwtIGxpc3QuZmlsZXMoaGVyZTo6aGVyZSgpLHJlY3Vyc2l2ZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIiouY3N2IiklPiUKICBtYXAofnJlYWRfY3N2KC4pKQoKCmNzdnNfbmFtZXMgPC0gbGlzdC5maWxlcyhyZWN1cnNpdmUgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIqLmNzdiIpJT4lCiAgc3RyX2V4dHJhY3QoIm55dHNbMl1bMF1bMV1bNS05XSIpCgpuYW1lcyhjc3ZzKSA8LSBjc3ZzX25hbWVzCgpueXRzX2RhdGEgPC0gY3N2cwpybShjc3ZzKQpybShjc3ZzX25hbWVzKQpgYGAKCgpgYGB7cn0KCm55dHNfZGF0YVtbIm55dHMyMDE1Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE1Il1dICU+JQogICAgIyBkcGx5cjo6c2VsZWN0KHBzdSwKICAgICMgICAgICAgICAgICAgICBmaW53Z3QsCiAgICAjICAgICAgICAgICAgICAgc3RyYXR1bSwKICAgICMgICAgICAgICAgICAgICBRbjEsICNBZ2UKICAgICMgICAgICAgICAgICAgICBRbjIsICNTZXgKICAgICMgICAgICAgICAgICAgICBRbjMsICNHcmFkZQogICAgIyAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJRbjQiKSwgI0hpc3BhbmljL0xhdGlubwogICAgIyAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJRbjUiKSwgI1JhY2UKICAgICMgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiRSIsCiAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAjICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLAogICAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgIyAgICAgICAgICAgICAgIC1FRkxBVkNJR1RTLAogICAgIyAgICAgICAgICAgICAgIC1DRkxBVkNJR1RTLAogICAgIyAgICAgICAgICAgICAgIC1FRkxBVkNJR0FSLAogICAgIyAgICAgICAgICAgICAgICkgJT4lCiAgICByZW5hbWUoQWdlPVFuMSwKICAgICAgICAgICBmZW1hbGU9UW4yLAogICAgICAgICAgIEdyYWRlPVFuMywKICAgICAgICAgICBOb3RfSEw9UW40YSwKICAgICAgICAgICBITF9NZXg9UW40YiwKICAgICAgICAgICBITF9QUj1RbjRjLAogICAgICAgICAgIEhMX0N1Yj1RbjRkLAogICAgICAgICAgIEhMX090aGVyPVFuNGUsCiAgICAgICAgICAgUmFjZV9BSUFOPVFuNWEsCiAgICAgICAgICAgUmFjZV9Bc2lhbj1RbjViLAogICAgICAgICAgIFJhY2VfQkFBPVFuNWMsCiAgICAgICAgICAgUmFjZV9OSE9QST1RbjVkLAogICAgICAgICAgIFJhY2VfV2hpdGU9UW41ZSkgJT4lCiAgICBtdXRhdGUoQWdlPUFnZSs4LAogICAgICAgICAgIEdyYWRlPUdyYWRlKzUsCiAgICAgICAgICAgYnJhbmRfZWNpZz1OQSwKICAgICAgICAgICBtZW50aG9sPU5BLAogICAgICAgICAgIGNsb3ZlX3NwaWNlPU5BLAogICAgICAgICAgIGZydWl0PU5BLAogICAgICAgICAgIGNob2NvbGF0ZT1OQSwKICAgICAgICAgICBhbGNvaG9saWNfZHJpbms9TkEsCiAgICAgICAgICAgY2FuZHlfZGVzc2VydF9zd2VldHM9TkEsCiAgICAgICAgICAgb3RoZXI9TkEsCiAgICAgICAgICAgbm9fdXNlPU5BKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1zdGFydHNfd2l0aCgiUSIpKQpgYGAKCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyfQojIFNjcm9sbCB0aHJvdWdoIHRoZSBvdXRwdXQhCgoKYGBgCiMjIyMKCmBgYHtyLCBldmFsID0gRkFMU0V9CnNhcHBseShueXRzX2RhdGFbWyJueXRzMjAxNSJdXSwgZnVuY3Rpb24oeCkKICAgIHN1bW1hcnkoCiAgICAgICAgZmFjdG9yKHgpCiAgICAgICAgKQogICAgKQpgYGAKCmBgYHtyfQojTm90ZSBhYm91dCBkaWZmZXJlbmNlIGJldHdlZW4gcmVjb2RlIGFuZCBmY3RfcmVjb2RlCm55dHNfZGF0YVtbIm55dHMyMDE1Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE1Il1dICU+JQogIG11dGF0ZV9hbGwofiByZXBsYWNlKC4sIC4gJWluJSBjKCIuIiksIE5BKSkgJT4lCiAgbXV0YXRlKEFnZT1hcy5jaGFyYWN0ZXIoQWdlKSwKICAgICAgICAgR3JhZGU9YXMuY2hhcmFjdGVyKEdyYWRlKQogICAgICAgICApICU+JQogIG11dGF0ZShBZ2U9cmVjb2RlKEFnZSwKICAgICAgICAgICAgICAgICAgICBgMTlgID0gIj4xOCIsCiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgZmVtYWxlPXJlY29kZShmZW1hbGUsCiAgICAgICAgICAgICAgICAgICAgICBgMWA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgYDJgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IE5BKSwKICAgICAgICAgR3JhZGU9cmVjb2RlKEdyYWRlLAogICAgICAgICAgICAgICAgICAgICAgYDEzYCA9ICJVbmdyYWRlZC9PdGhlciIpLAogICAgICAgICBOb3RfSEw9cmVjb2RlKE5vdF9ITCwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkhMIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIlJhY2UiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAyYCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IE5BLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBOQSkpKQpgYGAKCmBgYHtyLCBldmFsID0gRkFMU0V9CnNhcHBseShueXRzX2RhdGFbWyJueXRzMjAxNSJdXSwgZnVuY3Rpb24oeCkKICAgIHN1bW1hcnkoCiAgICAgICAgZmFjdG9yKHgpCiAgICAgICAgKQogICAgKQpgYGAKCmBgYHtyfQpueXRzX2RhdGFbWyJueXRzMjAxNiJdXSA8LSBueXRzX2RhdGFbWyJueXRzMjAxNiJdXSAlPiUKICAgIGRwbHlyOjpzZWxlY3QocHN1LAogICAgICAgICAgICAgICAgICBmaW53Z3QsCiAgICAgICAgICAgICAgICAgIHN0cmF0dW0sCiAgICAgICAgICAgICAgICAgIFExLCAjQWdlCiAgICAgICAgICAgICAgICAgIFEyLCAjU2V4CiAgICAgICAgICAgICAgICAgIFEzLCAjR3JhZGUKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlE0IiksICNIaXNwYW5pYy9MYXRpbm8KICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlE1IiksICNSYWNlCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJFIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIC1FRkxBVkNJR0FSLAogICAgICAgICAgICAgICAgICBRNTBBLCAjTWVudGhvbCAjIFdoYXQgZmxhdm9ycyBvZiB0b2JhY2NvIHByb2R1Y3RzIGhhdmUgeW91IHVzZWQgaW4gdGhlIHBhc3QgMzAgZGF5cz8gKFNlbGVjdCBvbmUgb3IgbW9yZSkKICAgICAgICAgICAgICAgICAgUTUwQiwgI0Nsb3ZlIG9yIHNwaWNlCiAgICAgICAgICAgICAgICAgIFE1MEMsICNGcnVpdAogICAgICAgICAgICAgICAgICBRNTBELCAjQ2hvY29sYXRlCiAgICAgICAgICAgICAgICAgIFE1MEUsICNBbGNvaG9saWMgRHJpbmsKICAgICAgICAgICAgICAgICAgUTUwRiwgI0NhbmR5L0Rlc3NlcnRzL090aGVyIFN3ZWV0cwogICAgICAgICAgICAgICAgICBRNTBHLCAjU29tZSBPdGhlciBGbGF2b3IgTm90IExpc3RlZCBIZXJlCiAgICAgICAgICAgICAgICAgIFE1MEggI0kgRGlkIE5vdCBVc2UgRmxhdm9yZWQgVG9iYWNjbyBQcm9kdWN0cyBJbiB0aGUgUGFzdAogICAgICAgICAgICAgICAgICApICU+JQogICAgcmVuYW1lKEFnZT1RMSwKICAgICAgICAgICBmZW1hbGU9UTIsCiAgICAgICAgICAgR3JhZGU9UTMsCiAgICAgICAgICAgTm90X0hMPVE0QSwKICAgICAgICAgICBITF9NZXg9UTRCLAogICAgICAgICAgIEhMX1BSPVE0QywKICAgICAgICAgICBITF9DdWI9UTRELAogICAgICAgICAgIEhMX090aGVyPVE0RSwKICAgICAgICAgICBSYWNlX0FJQU49UTVBLAogICAgICAgICAgIFJhY2VfQXNpYW49UTVCLAogICAgICAgICAgIFJhY2VfQkFBPVE1QywKICAgICAgICAgICBSYWNlX05IT1BJPVE1RCwKICAgICAgICAgICBSYWNlX1doaXRlPVE1RSwKICAgICAgICAgICBmZW1hbGU9UTIsCiAgICAgICAgICAgbWVudGhvbD1RNTBBLAogICAgICAgICAgIGNsb3ZlX3NwaWNlPVE1MEIsCiAgICAgICAgICAgZnJ1aXQ9UTUwQywKICAgICAgICAgICBjaG9jb2xhdGU9UTUwRCwKICAgICAgICAgICBhbGNvaG9saWNfZHJpbms9UTUwRSwKICAgICAgICAgICBjYW5keV9kZXNzZXJ0X3N3ZWV0cz1RNTBGLAogICAgICAgICAgIG90aGVyPVE1MEcsCiAgICAgICAgICAgbm9fdXNlPVE1MEgpICU+JQogICAgbXV0YXRlKEFnZSA9IGFzLm51bWVyaWMoQWdlKSArIDgsCiAgICAgICAgICAgR3JhZGUgPSBhcy5udW1lcmljKEdyYWRlKSArIDUsCiAgICAgICAgICAgYnJhbmRfZWNpZz1OQSkgJT4lCiAgZHBseXI6OnNlbGVjdCgtc3RhcnRzX3dpdGgoIlEiKSkKCiMgc2FwcGx5KG55dHNfZGF0YVtbIm55dHMyMDE2Il1dLCBmdW5jdGlvbih4KQojICAgICBzdW1tYXJ5KAojICAgICAgICAgZmFjdG9yKHgpCiMgICAgICAgICApCiMgICAgICkKCm55dHNfZGF0YVtbIm55dHMyMDE2Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE2Il1dICU+JQogIG11dGF0ZV9hbGwofiByZXBsYWNlKC4sIC4gJWluJSBjKCIqIiwgIioqIiksIE5BKSkgJT4lCiAgbXV0YXRlKEFnZT1hcy5jaGFyYWN0ZXIoQWdlKSwKICAgICAgICAgR3JhZGU9YXMuY2hhcmFjdGVyKEdyYWRlKQogICAgICAgICApICU+JQogIG11dGF0ZShBZ2U9cmVjb2RlKEFnZSwKICAgICAgICAgICAgICAgICAgICBgMTlgID0gIj4xOCIsCiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgZmVtYWxlPXJlY29kZShmZW1hbGUsCiAgICAgICAgICAgICAgICAgICAgICBgMWA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgYDJgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gTkEsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IE5BKSwKICAgICAgICAgR3JhZGU9cmVjb2RlKEdyYWRlLAogICAgICAgICAgICAgICAgICAgICAgYDEzYCA9ICJVbmdyYWRlZC9PdGhlciIpLAogICAgICAgICBOb3RfSEw9cmVjb2RlKE5vdF9ITCwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkhMIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIlJhY2UiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICAgIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDJgID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkgJT4lCiAgICBtdXRhdGVfYXQodmFycyhtZW50aG9sOm5vX3VzZSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkKCiMgc2FwcGx5KG55dHNfZGF0YVtbIm55dHMyMDE2Il1dLCBmdW5jdGlvbih4KQojICAgICBzdW1tYXJ5KAojICAgICAgICAgZmFjdG9yKHgpCiMgICAgICAgICApCiMgICAgICkKYGBgCgpgYGB7cn0Kbnl0c19kYXRhW1sibnl0czIwMTciXV0gPC0gbnl0c19kYXRhW1sibnl0czIwMTciXV0gJT4lCiAgICBkcGx5cjo6c2VsZWN0KHBzdSwKICAgICAgICAgICAgICAgICAgZmlud2d0LAogICAgICAgICAgICAgICAgICBzdHJhdHVtLAogICAgICAgICAgICAgICAgICBRMSwgI0FnZQogICAgICAgICAgICAgICAgICBRMiwgI1NleAogICAgICAgICAgICAgICAgICBRMywgI0dyYWRlCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJRNCIpLCAjSGlzcGFuaWMvTGF0aW5vCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJRNSIpLCAjUmFjZQogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiRSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgICAgICAgICAgICAgICBDQklESVMsCiAgICAgICAgICAgICAgICAgIFE1MEEsICNNZW50aG9sICMgV2hhdCBmbGF2b3JzIG9mIHRvYmFjY28gcHJvZHVjdHMgaGF2ZSB5b3UgdXNlZCBpbiB0aGUgcGFzdCAzMCBkYXlzPyAoU2VsZWN0IG9uZSBvciBtb3JlKQogICAgICAgICAgICAgICAgICBRNTBCLCAjQ2xvdmUgb3Igc3BpY2UKICAgICAgICAgICAgICAgICAgUTUwQywgI0ZydWl0CiAgICAgICAgICAgICAgICAgIFE1MEQsICNDaG9jb2xhdGUKICAgICAgICAgICAgICAgICAgUTUwRSwgI0FsY29ob2xpYyBEcmluawogICAgICAgICAgICAgICAgICBRNTBGLCAjQ2FuZHkvRGVzc2VydHMvT3RoZXIgU3dlZXRzCiAgICAgICAgICAgICAgICAgIFE1MEcsICNTb21lIE90aGVyIEZsYXZvciBOb3QgTGlzdGVkIEhlcmUKICAgICAgICAgICAgICAgICAgUTUwSCAjSSBEaWQgTm90IFVzZSBGbGF2b3JlZCBUb2JhY2NvIFByb2R1Y3RzIEluIHRoZSBQYXN0CiAgICAgICAgICAgICAgICAgICkgJT4lCiAgICByZW5hbWUoQWdlPVExLAogICAgICAgICAgIGZlbWFsZT1RMiwKICAgICAgICAgICBHcmFkZT1RMywKICAgICAgICAgICBOb3RfSEw9UTRBLAogICAgICAgICAgIEhMX01leD1RNEIsCiAgICAgICAgICAgSExfUFI9UTRDLAogICAgICAgICAgIEhMX0N1Yj1RNEQsCiAgICAgICAgICAgSExfT3RoZXI9UTRFLAogICAgICAgICAgIFJhY2VfQUlBTj1RNUEsCiAgICAgICAgICAgUmFjZV9Bc2lhbj1RNUIsCiAgICAgICAgICAgUmFjZV9CQUE9UTVDLAogICAgICAgICAgIFJhY2VfTkhPUEk9UTVELAogICAgICAgICAgIFJhY2VfV2hpdGU9UTVFLAogICAgICAgICAgIGZlbWFsZT1RMiwKICAgICAgICAgICBtZW50aG9sPVE1MEEsCiAgICAgICAgICAgY2xvdmVfc3BpY2U9UTUwQiwKICAgICAgICAgICBmcnVpdD1RNTBDLAogICAgICAgICAgIGNob2NvbGF0ZT1RNTBELAogICAgICAgICAgIGFsY29ob2xpY19kcmluaz1RNTBFLAogICAgICAgICAgIGNhbmR5X2Rlc3NlcnRfc3dlZXRzPVE1MEYsCiAgICAgICAgICAgb3RoZXI9UTUwRywKICAgICAgICAgICBub191c2U9UTUwSCkgJT4lCiAgICBtdXRhdGUoQWdlID0gYXMubnVtZXJpYyhBZ2UpICsgOCwKICAgICAgICAgICBHcmFkZSA9IGFzLm51bWVyaWMoR3JhZGUpICsgNSwKICAgICAgICAgICBicmFuZF9lY2lnPU5BKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1zdGFydHNfd2l0aCgiUSIpKQoKIyBzYXBwbHkobnl0c19kYXRhW1sibnl0czIwMTciXV0sIGZ1bmN0aW9uKHgpCiMgICAgIHN1bW1hcnkoCiMgICAgICAgICBmYWN0b3IoeCkKIyAgICAgICAgICkKIyAgICAgKQoKbnl0c19kYXRhW1sibnl0czIwMTciXV0gPC0gbnl0c19kYXRhW1sibnl0czIwMTciXV0gJT4lCiAgbXV0YXRlX2FsbCh+IHJlcGxhY2UoLiwgLiAlaW4lIGMoIioiLCAiKioiKSwgTkEpKSAlPiUKICBtdXRhdGUoQWdlPWFzLmNoYXJhY3RlcihBZ2UpLAogICAgICAgICBHcmFkZT1hcy5jaGFyYWN0ZXIoR3JhZGUpCiAgICAgICAgICkgJT4lCiAgbXV0YXRlKEFnZT1yZWNvZGUoQWdlLAogICAgICAgICAgICAgICAgICAgIGAxOWAgPSAiPjE4IiwKICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICBmZW1hbGU9cmVjb2RlKGZlbWFsZSwKICAgICAgICAgICAgICAgICAgICAgIGAxYD0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBgMmAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gTkEpLAogICAgICAgICBHcmFkZT1yZWNvZGUoR3JhZGUsCiAgICAgICAgICAgICAgICAgICAgICBgMTNgID0gIlVuZ3JhZGVkL090aGVyIiksCiAgICAgICAgIE5vdF9ITD1yZWNvZGUoTm90X0hMLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSAlPiUKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiSEwiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICBtdXRhdGVfYXQodmFycyhzdGFydHNfd2l0aCgiUmFjZSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkpICU+JQogICAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICBgMmAgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICAgIG11dGF0ZV9hdCh2YXJzKG1lbnRob2w6bm9fdXNlKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKQoKIyBzYXBwbHkobnl0c19kYXRhW1sibnl0czIwMTciXV0sIGZ1bmN0aW9uKHgpCiMgICAgIHN1bW1hcnkoCiMgICAgICAgICBmYWN0b3IoeCkKIyAgICAgICAgICkKIyAgICAgKQpgYGAKCmBgYHtyfQpueXRzX2RhdGFbWyJueXRzMjAxOCJdXSA8LSBueXRzX2RhdGFbWyJueXRzMjAxOCJdXSAlPiUKICAgIGRwbHlyOjpzZWxlY3QocHN1LAogICAgICAgICAgICAgICAgICBmaW53Z3QsCiAgICAgICAgICAgICAgICAgIHN0cmF0dW0sCiAgICAgICAgICAgICAgICAgIFExLCAjQWdlCiAgICAgICAgICAgICAgICAgIFEyLCAjU2V4CiAgICAgICAgICAgICAgICAgIFEzLCAjR3JhZGUKICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlE0IiksICNIaXNwYW5pYy9MYXRpbm8KICAgICAgICAgICAgICAgICAgc3RhcnRzX3dpdGgoIlE1IiksICNSYWNlCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJFIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgIFE1MEEsICNNZW50aG9sICMgV2hhdCBmbGF2b3JzIG9mIHRvYmFjY28gcHJvZHVjdHMgaGF2ZSB5b3UgdXNlZCBpbiB0aGUgcGFzdCAzMCBkYXlzPyAoU2VsZWN0IG9uZSBvciBtb3JlKQogICAgICAgICAgICAgICAgICBRNTBCLCAjQ2xvdmUgb3Igc3BpY2UKICAgICAgICAgICAgICAgICAgUTUwQywgI0ZydWl0CiAgICAgICAgICAgICAgICAgIFE1MEQsICNDaG9jb2xhdGUKICAgICAgICAgICAgICAgICAgUTUwRSwgI0FsY29ob2xpYyBEcmluawogICAgICAgICAgICAgICAgICBRNTBGLCAjQ2FuZHkvRGVzc2VydHMvT3RoZXIgU3dlZXRzCiAgICAgICAgICAgICAgICAgIFE1MEcsICNTb21lIE90aGVyIEZsYXZvciBOb3QgTGlzdGVkIEhlcmUKICAgICAgICAgICAgICAgICAgUTUwSCAjSSBEaWQgTm90IFVzZSBGbGF2b3JlZCBUb2JhY2NvIFByb2R1Y3RzIEluIHRoZSBQYXN0CiAgICAgICAgICAgICAgICAgICkgJT4lCiAgICByZW5hbWUoQWdlPVExLAogICAgICAgICAgIGZlbWFsZT1RMiwKICAgICAgICAgICBHcmFkZT1RMywKICAgICAgICAgICBOb3RfSEw9UTRBLAogICAgICAgICAgIEhMX01leD1RNEIsCiAgICAgICAgICAgSExfUFI9UTRDLAogICAgICAgICAgIEhMX0N1Yj1RNEQsCiAgICAgICAgICAgSExfT3RoZXI9UTRFLAogICAgICAgICAgIFJhY2VfQUlBTj1RNUEsCiAgICAgICAgICAgUmFjZV9Bc2lhbj1RNUIsCiAgICAgICAgICAgUmFjZV9CQUE9UTVDLAogICAgICAgICAgIFJhY2VfTkhPUEk9UTVELAogICAgICAgICAgIFJhY2VfV2hpdGU9UTVFLAogICAgICAgICAgIGZlbWFsZT1RMiwKICAgICAgICAgICBtZW50aG9sPVE1MEEsCiAgICAgICAgICAgY2xvdmVfc3BpY2U9UTUwQiwKICAgICAgICAgICBmcnVpdD1RNTBDLAogICAgICAgICAgIGNob2NvbGF0ZT1RNTBELAogICAgICAgICAgIGFsY29ob2xpY19kcmluaz1RNTBFLAogICAgICAgICAgIGNhbmR5X2Rlc3NlcnRfc3dlZXRzPVE1MEYsCiAgICAgICAgICAgb3RoZXI9UTUwRywKICAgICAgICAgICBub191c2U9UTUwSCkgJT4lCiAgICBtdXRhdGUoQWdlID0gYXMubnVtZXJpYyhBZ2UpICsgOCwKICAgICAgICAgICBHcmFkZSA9IGFzLm51bWVyaWMoR3JhZGUpICsgNSwKICAgICAgICAgICBicmFuZF9lY2lnPU5BKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1zdGFydHNfd2l0aCgiUSIpKQoKIyBzYXBwbHkobnl0c19kYXRhW1sibnl0czIwMTgiXV0sIGZ1bmN0aW9uKHgpCiMgICAgIHN1bW1hcnkoCiMgICAgICAgICBmYWN0b3IoeCkKIyAgICAgICAgICkKIyAgICAgKQoKbnl0c19kYXRhW1sibnl0czIwMTgiXV0gPC0gbnl0c19kYXRhW1sibnl0czIwMTgiXV0gJT4lCiAgbXV0YXRlX2FsbCh+IHJlcGxhY2UoLiwgLiAlaW4lIGMoIioiLCAiKioiKSwgTkEpKSAlPiUKICBtdXRhdGUoQWdlPWFzLmNoYXJhY3RlcihBZ2UpLAogICAgICAgICBHcmFkZT1hcy5jaGFyYWN0ZXIoR3JhZGUpCiAgICAgICAgICkgJT4lCiAgICBtdXRhdGUoQWdlPXJlY29kZShBZ2UsCiAgICAgICAgICAgICAgICAgICAgYDE5YCA9ICI+MTgiLAogICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIGZlbWFsZT1yZWNvZGUoZmVtYWxlLAogICAgICAgICAgICAgICAgICAgICAgYDFgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGAyYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IE5BLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBOQSksCiAgICAgICAgIEdyYWRlPXJlY29kZShHcmFkZSwKICAgICAgICAgICAgICAgICAgICAgIGAxM2AgPSAiVW5ncmFkZWQvT3RoZXIiKSwKICAgICAgICAgTm90X0hMPXJlY29kZShOb3RfSEwsCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJITCIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkpICU+JQogIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJSYWNlIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSwKICAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICBgMmAgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gTkEpKSkgJT4lCiAgICBtdXRhdGVfYXQodmFycyhtZW50aG9sOm5vX3VzZSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkKCiMgc2FwcGx5KG55dHNfZGF0YVtbIm55dHMyMDE4Il1dLCBmdW5jdGlvbih4KQojICAgICBzdW1tYXJ5KAojICAgICAgICAgZmFjdG9yKHgpCiMgICAgICAgICApCiMgICAgICkKYGBgCgpgYGB7cn0Kbnl0c19kYXRhW1sibnl0czIwMTkiXV0gPC0gbnl0c19kYXRhW1sibnl0czIwMTkiXV0gJT4lCiAgICBkcGx5cjo6c2VsZWN0KHBzdSwKICAgICAgICAgICAgICAgICAgZmlud2d0LAogICAgICAgICAgICAgICAgICBzdHJhdHVtLAogICAgICAgICAgICAgICAgICBRMSwgI0FnZQogICAgICAgICAgICAgICAgICBRMiwgI1NleAogICAgICAgICAgICAgICAgICBRMywgI0dyYWRlCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJRNCIpLCAjSGlzcGFuaWMvTGF0aW5vCiAgICAgICAgICAgICAgICAgIHN0YXJ0c193aXRoKCJRNSIpLCAjUmFjZQogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiRSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlnbm9yZS5jYXNlID0gRkFMU0UpLAogICAgICAgICAgICAgICAgICAtRUhUUCwKICAgICAgICAgICAgICAgICAgLUNIVFAsCiAgICAgICAgICAgICAgICAgIFE0MCwgI0JyYW5nLCBlLWNpZ2FyZXR0ZXMKICAgICAgICAgICAgICAgICAgUTYyQSwgI01lbnRob2wgIyBXaGF0IGZsYXZvcnMgb2YgdG9iYWNjbyBwcm9kdWN0cyBoYXZlIHlvdSB1c2VkIGluIHRoZSBwYXN0IDMwIGRheXM/IChTZWxlY3Qgb25lIG9yIG1vcmUpCiAgICAgICAgICAgICAgICAgIFE2MkIsICNDbG92ZSBvciBzcGljZQogICAgICAgICAgICAgICAgICBRNjJDLCAjRnJ1aXQgCiAgICAgICAgICAgICAgICAgIFE2MkQsICNDaG9jb2xhdGUKICAgICAgICAgICAgICAgICAgUTYyRSwgI0FsY29ob2xpYyBEcmluawogICAgICAgICAgICAgICAgICBRNjJGLCAjQ2FuZHkvRGVzc2VydHMvT3RoZXIgU3dlZXRzCiAgICAgICAgICAgICAgICAgIFE2MkcsICNTb21lIE90aGVyIEZsYXZvciBOb3QgTGlzdGVkIEhlcmUgCiAgICAgICAgICAgICAgICAgICkgICU+JQogICAgcmVuYW1lKGJyYW5kX2VjaWc9UTQwLAogICAgICAgICAgIEFnZT1RMSwKICAgICAgICAgICBmZW1hbGU9UTIsCiAgICAgICAgICAgR3JhZGU9UTMsCiAgICAgICAgICAgTm90X0hMPVE0QSwKICAgICAgICAgICBITF9NZXg9UTRCLAogICAgICAgICAgIEhMX1BSPVE0QywKICAgICAgICAgICBITF9DdWI9UTRELAogICAgICAgICAgIEhMX090aGVyPVE0RSwKICAgICAgICAgICBSYWNlX0FJQU49UTVBLAogICAgICAgICAgIFJhY2VfQXNpYW49UTVCLAogICAgICAgICAgIFJhY2VfQkFBPVE1QywKICAgICAgICAgICBSYWNlX05IT1BJPVE1RCwKICAgICAgICAgICBSYWNlX1doaXRlPVE1RSwKICAgICAgICAgICBmZW1hbGU9UTIsCiAgICAgICAgICAgbWVudGhvbD1RNjJBLAogICAgICAgICAgIGNsb3ZlX3NwaWNlPVE2MkIsCiAgICAgICAgICAgZnJ1aXQ9UTYyQywKICAgICAgICAgICBjaG9jb2xhdGU9UTYyRCwKICAgICAgICAgICBhbGNvaG9saWNfZHJpbms9UTYyRSwKICAgICAgICAgICBjYW5keV9kZXNzZXJ0X3N3ZWV0cz1RNjJGLAogICAgICAgICAgIG90aGVyPVE2MkcpICU+JQogICAgbXV0YXRlKEFnZSA9IGFzLm51bWVyaWMoQWdlKSArIDgsCiAgICAgICAgICAgR3JhZGUgPSBhcy5udW1lcmljKEdyYWRlKSArIDUsCiAgICAgICAgICAgbm9fdXNlPSJtaXNzaW5nIikgJT4lCiAgZHBseXI6OnNlbGVjdCgtc3RhcnRzX3dpdGgoIlEiKSkKCiMgc2FwcGx5KG55dHNfZGF0YVtbIm55dHMyMDE5Il1dLCBmdW5jdGlvbih4KQojICAgICBzdW1tYXJ5KAojICAgICAgICAgZmFjdG9yKHgpCiMgICAgICAgICApCiMgICAgICkKCm55dHNfZGF0YVtbIm55dHMyMDE5Il1dIDwtIG55dHNfZGF0YVtbIm55dHMyMDE5Il1dICU+JQogIG11dGF0ZV9hbGwofiByZXBsYWNlKC4sIC4gJWluJSBjKCIuTiIsIi5TIiwiLloiKSwgTkEpKSAlPiUKICBtdXRhdGUoQWdlPWFzLmNoYXJhY3RlcihBZ2UpLAogICAgICAgICBHcmFkZT1hcy5jaGFyYWN0ZXIoR3JhZGUpCiAgICAgICAgICkgJT4lCiAgbXV0YXRlKHBzdT1hcy5jaGFyYWN0ZXIocHN1KSwKICAgICAgICAgQWdlPXJlY29kZShBZ2UsCiAgICAgICAgICAgICAgICAgICAgYDE5YCA9ICI+MTgiLAogICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgIGZlbWFsZT1yZWNvZGUoZmVtYWxlLAogICAgICAgICAgICAgICAgICAgICAgYDFgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGAyYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IE5BKSwKICAgICAgICAgR3JhZGU9cmVjb2RlKEdyYWRlLAogICAgICAgICAgICAgICAgICAgICAgYDEzYCA9ICJVbmdyYWRlZC9PdGhlciIpLAogICAgICAgICBOb3RfSEw9cmVjb2RlKE5vdF9ITCwKICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAubWlzc2luZyA9IEZBTFNFKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIkhMIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpLAogICAgICAgICAgICAgIGxpc3QofnJlY29kZSguLAogICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID0gRkFMU0UpKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoc3RhcnRzX3dpdGgoIlJhY2UiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAuZGVmYXVsdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgLm1pc3NpbmcgPSBGQUxTRSkpKSAlPiUKICAgIG11dGF0ZV9hdCh2YXJzKHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSksCiAgICAgICAgICAgICAgICAgICBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSwKICAgICAgICAgICAgICBsaXN0KH5yZWNvZGUoLiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDFgID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYDJgID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gTkEpKSkgJT4lCiAgICBtdXRhdGUoYnJhbmRfZWNpZyA9IHJlY29kZShicmFuZF9lY2lnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMWAgPSAiT3RoZXIiLCAjbGV2ZWxzIDEsOCBjb21iaW5lZCB0byBgT3RoZXJgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgMmAgPSAiQmx1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYDNgID0gIkpVVUwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgNGAgPSAiTG9naWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgNWAgPSAiTWFya1RlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGA2YCA9ICJOSk9ZIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYDdgID0gIlZ1c2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgOGAgPSAiT3RoZXIiKSkgJT4lCiAgICBtdXRhdGVfYXQodmFycyhtZW50aG9sOm5vX3VzZSksCiAgICAgICAgICAgICAgbGlzdCh+cmVjb2RlKC4sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGAxYCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC5taXNzaW5nID1GQUxTRSkpKSAjQXNrIE1pY2hhZWwgYWJvdXQgdGhpcyBpZiB1bmNsZWFyCgojIHNhcHBseShueXRzX2RhdGFbWyJueXRzMjAxOSJdXSwgZnVuY3Rpb24oeCkKIyAgICAgc3VtbWFyeSgKIyAgICAgICAgIGZhY3Rvcih4KQojICAgICAgICAgKQojICAgICApCmBgYAoKYGBge3J9Cm55dHNfZGF0YSA8LSBueXRzX2RhdGEgJT4lCiAgbWFwX2RmKGJpbmRfcm93cywgLmlkID0gInllYXIiKSAlPiUKICBtdXRhdGUoeWVhcj1hcy5udW1lcmljKHN0cl9yZW1vdmUoeWVhciwibnl0cyIpKSkKCiNzYXBwbHkobnl0c19kYXRhLCBjbGFzcykKCiMgc2FwcGx5KG55dHNfZGF0YSwgZnVuY3Rpb24oeCkKIyAgICAgc3VtbWFyeSgKIyAgICAgICAgIGZhY3Rvcih4KQojICAgICAgICAgKQojICAgICApCgoKYGBgCgo8c3R5bGU+CmRpdi5ibHVlIHsgYmFja2dyb3VuZC1jb2xvcjojZTZmMGZmOyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gImJsdWUiPgoKUmVtaW5kZXI6IEN1cnJlbnQgdXNlcnMgYXJlIGEgc3Vic2V0IG9mIGV2ZXIgdXNlcnMuIAoKPC9kaXY+CgoKCiMjICoqRGF0YSBFeHBsb3JhdGlvbiBhbmQgV3JhbmdsaW5nKioKKioqIAoKV2Ugd2lsbCBhbHNvIHVzZSB0aGUgYCU+JWAgcGlwZSB3aGljaCBjYW4gYmUgdXNlZCB0byBkZWZpbmUgdGhlIGlucHV0IGZvciBsYXRlciBzZXF1ZW50aWFsIHN0ZXBzLiBUaGlzIHdpbGwgbWFrZSBtb3JlIHNlbnNlIHdoZW4gd2UgaGF2ZSBtdWx0aXBsZSBzZXF1ZW50aWFsIHN0ZXBzIHVzaW5nIHRoZSBzYW1lIGRhdGEgb2JqZWN0LiBUbyB1c2UgdGhlIHBpcGUgbm90YXRpb24gd2UgbmVlZCB0byBpbnN0YWxsIGFuZCBsb2FkIGRwbHlyIGFzIHdlbGwuCgoKCiMjICoqRGF0YSBWaXN1YWxpemF0aW9uKioKKioqIAoKIyMjIFF1ZXN0aW9uIDEgCgpGb3IgbG90cyBvZiBwaXZvdF9sb25nZXIoKSB0aGF0IGFyZSB0aGUgc2FtZS4uLiBjYW4gdXNlIHBpdm90X2xvbmdlcl9zcGVjKCkKCnNwZWMgPC0gcmVsaWdfaW5jb21lICU+JSBidWlsZF9sb25nZXJfc3BlYygKICBjb2xzID0gLXJlbGlnaW9uLAogIG5hbWVzX3RvID0gImluY29tZSIsCiAgdmFsdWVzX3RvID0gImNvdW50IgopCnBpdm90X2xvbmdlcl9zcGVjKHJlbGlnX2luY29tZSwgc3BlYykKCkJ1dCBuZWVkIHRvIGRlY2lkZSBpZiB3ZSBhcmUgZ29pbmcgdG8gY3JlYXRlIHNvbWUgbmV3IGRhdGEgZnJhbWVzLi4uCgpgYGB7cn0KcGxvdDEgPC0gbnl0c19kYXRhICU+JQogICAgbXV0YXRlKHRvYmFjY29fc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgdG9iYWNjb19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUodG9iYWNjb19ldmVyID0gY2FzZV93aGVuKHRvYmFjY29fc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9iYWNjb19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgdG9iYWNjb19jdXJyZW50ID0gY2FzZV93aGVuKHRvYmFjY29fc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9iYWNjb19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogICAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgICBzdW1tYXJpc2UodG9iYWNjb19ldmVyX3llYXI9KHN1bSh0b2JhY2NvX2V2ZXIsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEodG9iYWNjb19ldmVyKSksCiAgICAgICAgICAgICAgdG9iYWNjb19jdXJyZW50X3llYXI9KHN1bSh0b2JhY2NvX2N1cnJlbnQsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEodG9iYWNjb19jdXJyZW50KSkpICU+JQogICAgcmVuYW1lKCJFdmVyIj10b2JhY2NvX2V2ZXJfeWVhciwKICAgICAgICAgICAiQ3VycmVudCI9dG9iYWNjb19jdXJyZW50X3llYXIpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gLXllYXIsIG5hbWVzX3RvID0gIlVzZXIiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcix5PWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwgbGluZXR5cGU9VXNlcikpICsKICAgIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxKSkgKwogICAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDcwLGJ5PTEwKSwKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMCw3MCxieT0xMCksCiAgICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDcwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIkhvdyBkb2VzIG5pY290aW5lIHVzZSB2YXJ5IG92ZXIgdGhlIHllYXJzPyIsCiAgICAgICAgIHN1YnRpdGxlID0gIkN1cnJlbnQgYW5kIGV2ZXIgdXNlcnMgb2Ygbmljb3RpbmUgcHJvZHVjdHMiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKcGxvdDEgCmBgYAoKIyMjIFF1ZXN0aW9uIDIKCmBgYHtyfQpwbG90MiA8LSBueXRzX2RhdGEgJT4lCiAgICBncm91cF9ieSh5ZWFyLAogICAgICAgICAgICAgZmVtYWxlKSAlPiUKICAgIHN1bW1hcmlzZShFRUxDSUdUX3llYXI9KHN1bShFRUxDSUdULCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKEVFTENJR1QpKSwKICAgICAgICAgICAgICBDRUxDSUdUX3llYXI9KHN1bShDRUxDSUdULCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKENFTENJR1QpKSkgJT4lIAogICAgZmlsdGVyKCFpcy5uYShmZW1hbGUpKSAlPiUKICAgIHJlbmFtZSgiRS1jaWdhcmV0dGVzLCBFdmVyIj1FRUxDSUdUX3llYXIsCiAgICAgICAgICAgIkUtY2lnYXJldHRlcywgQ3VycmVudCI9Q0VMQ0lHVF95ZWFyKSAlPiUKICAjY29udmVydGluZyBhbGwgY29sdW1ucyBiZXR3ZWVuIGFuZCBpbmNsdWRpbmcgYEUtY2lnYXJldHRlcywgRXZlcmAgYW5kIGBFLWNpZ2FyZXR0ZXMsIEN1cnJlbnRgIGludG8gb25lIGNvbHVtbiBjYWxsZWQgY2F0ZWdvcnkKICAgIHBpdm90X2xvbmdlcihjb2xzID0gYEUtY2lnYXJldHRlcywgRXZlcmA6YEUtY2lnYXJldHRlcywgQ3VycmVudGAsIG5hbWVzX3RvID0gIkNhdGVnb3J5IiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSU+JQogICAgbXV0YXRlKFVzZXIgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0gIkUtY2lnYXJldHRlcywgRXZlciIgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSAiRS1jaWdhcmV0dGVzLCBDdXJyZW50IiB+ICJDdXJyZW50IikpICU+JQogICAgbXV0YXRlKFNleCA9IGNhc2Vfd2hlbihmZW1hbGUgPT0gVFJVRSB+ICJGZW1hbGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlbWFsZSA9PSBGQUxTRSB+ICJNYWxlcyIpKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLCBjb2xvcj1TZXgsIGxpbmV0eXBlPVVzZXIpKSArCiAgICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIkhvdyBkbyB2YXBpbmcgcmF0ZXMgY29tcGFyZSBiZXR3ZWVuIG1hbGVzIGFuZCBmZW1hbGVzPyIsCiAgICAgICAgIHN1YnRpdGxlID0gIkN1cnJlbnQgYW5kIGV2ZXIgdXNlcnMgYnkgZ2VuZGVyIiwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnBsb3QyCmBgYAoKIyMjIFF1ZXN0aW9uIDMKCldoYXQgdmFwaW5nIGJyYW5kcyBhbmQgZmxhdm9ycyBhcHBlYXIgdG8gYmUgdXNlZCB0aGUgbW9zdCBmcmVxdWVudGx5PwoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5jYXA9Ikh1YW5nIEosIER1YW4gWiwgS3dvayBKLCBldCBhbC4gVG9iIENvbnRyb2wgMjAxOTsyODoxNDbigJMxNTEuIiwgb3V0LndpZHRoID0gJzEwMCUnfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiSHVhbmdKX0R1YW5aX0t3b2tKX2V0X2FsX1RvYmFjY29Db250cm9sX0ZpZ3VyZTEucG5nIikpCmBgYAoKW1BhcGVyXShodHRwczovL3RvYmFjY29jb250cm9sLmJtai5jb20vY29udGVudC90b2JhY2NvY29udHJvbC8yOC8yLzE0Ni5mdWxsLnBkZikKCgpgYGB7cn0KcGxvdDMgPC0gbnl0c19kYXRhICU+JQogICAgZmlsdGVyKHllYXI9PTIwMTkpICU+JQogICAgZ3JvdXBfYnkoYnJhbmRfZWNpZykgJT4lCiAgICBmaWx0ZXIoIWlzLm5hKGJyYW5kX2VjaWcpKSAlPiUKICAgIHN1bW1hcmlzZShuID0gbigpKSAlPiUKICAgIG11dGF0ZSh0b3RhbCA9IHN1bShuKSwKICAgICAgICAgICBQZXJjZW50ID0gbioxMDAvdG90YWwpICU+JQogICAgbXV0YXRlKGJyYW5kX2VjaWcgPSBmY3RfcmVvcmRlcihicmFuZF9lY2lnLCBkZXNjKFBlcmNlbnQpKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9YnJhbmRfZWNpZyx5PVBlcmNlbnQsIGZpbGw9YnJhbmRfZWNpZykpICsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIldoYXQgdmFwaW5nIGJyYW5kcyBhcHBlYXIgdG8gYmUgdXNlZCB0aGUgbW9zdCBmcmVxdWVudGx5PyIsCiAgICAgICAgIHN1YnRpdGxlID0gIkJyYW5kIG9mIGUtY2lnYXJldHRlIG1vc3QgZnJlcXVlbnRseSB1c2VkIGluIHRoZSBsYXN0IDMwIGRheXMgKDIwMTkpIiwKICAgICAgICAgeSA9ICIlIG9mIGUtY2lnYXJldHRlIHVzZXJzIHJlc3BvbmRpbmciKQoKcGxvdDMKYGBgCgpgYGB7cn0KcGxvdDQgPC0gbnl0c19kYXRhICU+JQogIGZpbHRlcih5ZWFyIT0yMDE1KSAlPiUKICBncm91cF9ieSh5ZWFyKSAlPiUKICBzdW1tYXJpc2UoTWVudGhvbD0oc3VtKG1lbnRob2wsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEobWVudGhvbCkpLAogICAgICAgICAgICAgIGBDbG92ZSBvciBTcGljZWA9KHN1bShjbG92ZV9zcGljZSwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShjbG92ZV9zcGljZSkpLAogICAgICAgICAgICAgIGBGcnVpdGA9KHN1bShmcnVpdCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShmcnVpdCkpLAogICAgICAgICAgICAgIGBDaG9jb2xhdGVgPShzdW0oY2hvY29sYXRlLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKGNob2NvbGF0ZSkpLAogICAgICAgICAgICAgIGBBbGNvaG9saWMgRHJpbmtgPShzdW0oYWxjb2hvbGljX2RyaW5rLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKGFsY29ob2xpY19kcmluaykpLAogICAgICAgICAgICAgIGBDYW5keS9EZXNzZXJ0cy9Td2VldHNgPShzdW0oY2FuZHlfZGVzc2VydF9zd2VldHMsIG5hLnJtID0gVFJVRSkqMTAwKS9zdW0oIWlzLm5hKGNhbmR5X2Rlc3NlcnRfc3dlZXRzKSkpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gLXllYXIsIG5hbWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiLCB2YWx1ZXNfdG8gPSAiRmxhdm9yIikgJT4lCgogIGdncGxvdChhZXMoeD15ZWFyLCB5PWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwgY29sb3I9Rmxhdm9yKSkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsgCiAgbGFicyh0aXRsZSA9ICJXaGF0IGZsYXZvcnMgYXBwZWFyIHRvIGJlIHVzZWQgdGhlIG1vc3QgZnJlcXVlbnRseSBpbiBuaWNvdGluZSBwcm9kdWN0cz8iLAogICAgICAgc3VidGl0bGUgPSAiRmxhdm9ycyBvZiB0b2JhY2NvIHByb2R1Y3RzIHVzZWQgaW4gdGhlIHBhc3QgMzAgZGF5cyIpCgpwbG90NCAKYGBgCgpgYGB7cn0KcGxvdDUgPC0gbnl0c19kYXRhICU+JQogIGZpbHRlcih5ZWFyIT0yMDE1KSAlPiUKICBmaWx0ZXIobWVudGhvbD09VFJVRXwKICAgICAgICAgICBjbG92ZV9zcGljZT09VFJVRXwKICAgICAgICAgICBmcnVpdD09VFJVRXwKICAgICAgICAgICBjaG9jb2xhdGU9PVRSVUV8CiAgICAgICAgICAgYWxjb2hvbGljX2RyaW5rPT1UUlVFfAogICAgICAgICAgIGNhbmR5X2Rlc3NlcnRfc3dlZXRzPT1UUlVFfAogICAgICAgICAgIG90aGVyPT1UUlVFKSAlPiUKICBtdXRhdGUoZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBFRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIENFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1DRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUoZWNpZ19ldmVyID0gY2FzZV93aGVuKGVjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfZXZlciA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogIG11dGF0ZShlY2lnX29ubHlfZXZlciA9IGNhc2Vfd2hlbihlY2lnX2V2ZXIgPT0gVFJVRSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlciA9PUZBTFNFIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX29ubHlfY3VycmVudCA9IGNhc2Vfd2hlbihlY2lnX2N1cnJlbnQgPT0gVFJVRSAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19ldmVyID09RkFMU0UgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX29ubHlfZXZlciA9IGNhc2Vfd2hlbihub25fZWNpZ19ldmVyID09IFRSVUUgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfZXZlciA9PUZBTFNFIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19vbmx5X2N1cnJlbnQgPSBjYXNlX3doZW4obm9uX2VjaWdfY3VycmVudCA9PSBUUlVFICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX2V2ZXIgPT1GQUxTRSB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiBGQUxTRSkpICU+JQogIG11dGF0ZShHcm91cCA9IGNhc2Vfd2hlbihlY2lnX29ubHlfZXZlcj09VFJVRSB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19vbmx5X2N1cnJlbnQ9PVRSVUUgfiAiT25seSBlLWNpZ2FyZXR0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfb25seV9ldmVyPT1UUlVFIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfb25seV9jdXJyZW50PT1UUlVFIH4gIk9ubHkgb3RoZXIgcHJvZHVjdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkJvdGgiKSkgJT4lCiAgZmlsdGVyKEdyb3VwIT0iQm90aCIpICU+JQogIGdyb3VwX2J5KHllYXIsIEdyb3VwKSAlPiUKICBzdW1tYXJpc2UoYE1lbnRob2xgPShzdW0obWVudGhvbCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgIHN1bSghaXMubmEobWVudGhvbCkpLAogICAgICAgICAgICAgIGBDbG92ZSBvciBTcGljZWA9KHN1bShjbG92ZV9zcGljZSwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgIHN1bSghaXMubmEoY2xvdmVfc3BpY2UpKSwKICAgICAgICAgICAgICBgRnJ1aXRgPShzdW0oZnJ1aXQsIG5hLnJtID0gVFJVRSkqMTAwKS9zdW0oIWlzLm5hKGZydWl0KSksCiAgICAgICAgICAgICAgYENob2NvbGF0ZWA9KHN1bShjaG9jb2xhdGUsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICBzdW0oIWlzLm5hKGNob2NvbGF0ZSkpLAogICAgICAgICAgICAgIGBBbGNvaG9saWMgRHJpbmtgPShzdW0oYWxjb2hvbGljX2RyaW5rLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgc3VtKCFpcy5uYShhbGNvaG9saWNfZHJpbmspKSwKICAgICAgICAgICAgICBgQ2FuZHkvRGVzc2VydHMvU3dlZXRzYD0oc3VtKGNhbmR5X2Rlc3NlcnRfc3dlZXRzLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgc3VtKCFpcy5uYShjYW5keV9kZXNzZXJ0X3N3ZWV0cykpLAogICAgICAgICAgICBgT3RoZXJgPShzdW0ob3RoZXIsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICBzdW0oIWlzLm5hKG90aGVyKSksCiAgICAgICAgICAgIFJlc3BvbmRlbnRzPW4oKSkgJT4lCiAgI2NvbnZlcnRpbmcgYWxsIGNvbHVtbnMgYmV0d2VlbiBhbmQgaW5jbHVkaW5nIE1lbnRob2wgYW5kIE90aGVyIHRvIG9uZSBjb2x1bW4gY2FsbGVkIEZsYXZvcgogIHBpdm90X2xvbmdlcihjb2xzID0gTWVudGhvbDpPdGhlciwgbmFtZXNfdG8gPSAiRmxhdm9yIiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCksCiAgICAgICAgIEZsYXZvciE9Ik90aGVyIikgJT4lCiAgZ3JvdXBfYnkoRmxhdm9yKSAlPiUKICBtdXRhdGUoYWZmaXJtYXRpdmU9KFJlc3BvbmRlbnRzICogYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKS8xMDApICU+JQogIG11dGF0ZShmbGF2b3JfbWVhbiA9IHN1bShhZmZpcm1hdGl2ZSkvc3VtKFJlc3BvbmRlbnRzKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShmbGF2b3JfbWVhbl9yYW5rID0gZGVuc2VfcmFuayhmbGF2b3JfbWVhbiksCiAgICAgICAgIEZsYXZvciA9IGZjdF9yZW9yZGVyKEZsYXZvciwgZmxhdm9yX21lYW5fcmFuaykpICU+JQogIGdncGxvdChhZXMoeD15ZWFyLCB5PWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwgY29sb3I9R3JvdXApKSArCiAgZmFjZXRfd3JhcCgufkZsYXZvcixuY29sPTMpICsKICBnZW9tX2xpbmUoKSArIAogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKyAKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSArIAogIGxhYnModGl0bGUgPSAiQW1vbmcgdXNlcnMgb2Ygb25seSBvbmUgdHlwZSBvZiBwcm9kdWN0LCB3aGF0IHZhcGluZyBmbGF2b3JzIGFwcGVhciB0byBiZSB1c2VkIHRoZSBtb3N0IGZyZXF1ZW50bHk/IiwKICAgICAgIHN1YnRpdGxlID0gIlBlcmNlbnQgcmVwb3J0aW5nIG9ubHkgZS1jaWdhcmV0dGUgdXNlIHZzIG9ubHkgb3RoZXIgbmljb3RpbmUgcHJvZHVjdCB1c2UiKQoKcGxvdDUKYGBgCgojIyMgUXVlc3Rpb24gNAoKSGF2ZSB2YXBpbmcgcmF0ZXMgcG9zc2libHkgaW5mbHVlbmNlZCB0b2JhY2NvL25pY290aW5lIHVzZT8KCmBgYHtyfQpwbG90NiA8LSBueXRzX2RhdGEgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICAgIHN1bW1hcmlzZShFQ0lHVF95ZWFyPShzdW0oRUNJR1QsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoRUNJR1QpKSwKICAgICAgICAgICAgICBFRUxDSUdUX3llYXI9KHN1bShFRUxDSUdULCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKEVFTENJR1QpKSwKICAgICAgICAgICAgICBDQ0lHVF95ZWFyPShzdW0oQ0NJR1QsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoQ0NJR1QpKSwKICAgICAgICAgICAgICBDRUxDSUdUX3llYXI9KHN1bShDRUxDSUdULCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKENFTENJR1QpKSkgJT4lCiAgICByZW5hbWUoIkNpZ2FyZXR0ZXMsIEV2ZXIiPUVDSUdUX3llYXIsCiAgICAgICAgICAgIkUtY2lnYXJldHRlcywgRXZlciI9RUVMQ0lHVF95ZWFyLAogICAgICAgICAgICJDaWdhcmV0dGVzLCBDdXJyZW50Ij1DQ0lHVF95ZWFyLAogICAgICAgICAgICJFLWNpZ2FyZXR0ZXMsIEN1cnJlbnQiPUNFTENJR1RfeWVhcikgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHM9IC15ZWFyLCBuYW1lc190byA9ICJDYXRlZ29yeSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIiklPiUKICAgICMgZ2F0aGVyKGtleT1DYXRlZ29yeSwKICAgICMgICAgICAgIHZhbHVlPWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwKICAgICMgICAgICAgIC15ZWFyKSAlPiUKICAgIG11dGF0ZShVc2VyID0gY2FzZV93aGVuKENhdGVnb3J5ID09ICJDaWdhcmV0dGVzLCBFdmVyIiB+ICJFdmVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ICJFLWNpZ2FyZXR0ZXMsIEV2ZXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0gIkNpZ2FyZXR0ZXMsIEN1cnJlbnQiIH4gIkN1cnJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0gIkUtY2lnYXJldHRlcywgQ3VycmVudCIgfiAiQ3VycmVudCIpKSAlPiUKICAgIG11dGF0ZShQcm9kdWN0ID0gY2FzZV93aGVuKENhdGVnb3J5ID09ICJDaWdhcmV0dGVzLCBFdmVyIiB+ICJDaWdhcmV0dGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ICJFLWNpZ2FyZXR0ZXMsIEV2ZXIiIH4gIkUtY2lnYXJldHRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSAiQ2lnYXJldHRlcywgQ3VycmVudCIgfiAiQ2lnYXJldHRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSAiRS1jaWdhcmV0dGVzLCBDdXJyZW50IiB+ICJFLWNpZ2FyZXR0ZXMiKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcix5PWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwgY29sb3I9UHJvZHVjdCwgbGluZXR5cGU9VXNlcikpICsKICAgIGdlb21fbGluZSgpICsgCiAgZ2VvbV9wb2ludChzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgc2NhbGVfbGluZXR5cGVfbWFudWFsKHZhbHVlcyA9IGMoMiwxKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIkhvdyBkb2VzIGUtY2lnYXJldHRlIHVzZSBjb21wYXJlIHRvIGNpZ2FyZXR0ZSB1c2U/IiwKICAgICAgICAgc3VidGl0bGUgPSAiQ3VycmVudCBhbmQgZXZlciB1c2VycyBvZiBlLWNpZ2FyZXR0ZXMgYW5kIGNpZ2FyZXR0ZXMiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKcGxvdDYKYGBgCgpgYGB7cn0KcGxvdDcgPC0gbnl0c19kYXRhICU+JQogICAgbXV0YXRlKGVjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBDRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSkpICU+JQogICAgbXV0YXRlKGVjaWdfZXZlciA9IGNhc2Vfd2hlbihlY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIGVjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihlY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX2V2ZXIgPSBjYXNlX3doZW4obm9uX2VjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4obm9uX2VjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpKSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogICAgc3VtbWFyaXNlKGVjaWdfZXZlcl95ZWFyPShzdW0oZWNpZ19ldmVyLCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKGVjaWdfZXZlcikpLAogICAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyPShzdW0oZWNpZ19jdXJyZW50LCBuYS5ybSA9IFRSVUUpKjEwMCkvCiAgICAgICAgICAgICAgICBzdW0oIWlzLm5hKGVjaWdfY3VycmVudCkpLAogICAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhcj0oc3VtKG5vbl9lY2lnX2V2ZXIsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEobm9uX2VjaWdfZXZlcikpLAogICAgICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnRfeWVhcj0oc3VtKG5vbl9lY2lnX2N1cnJlbnQsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEobm9uX2VjaWdfY3VycmVudCkpKSAlPiUKICAgIHBpdm90X2xvbmdlcihjb2xzID0gLXllYXIsIG5hbWVzX3RvID0gIkNhdGVnb3J5IiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSAlPiUKICAgIG11dGF0ZShVc2VyID0gY2FzZV93aGVuKENhdGVnb3J5ID09ImVjaWdfZXZlcl95ZWFyIiB+ICJFdmVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0ibm9uX2VjaWdfZXZlcl95ZWFyIiB+ICJFdmVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0iZWNpZ19jdXJyZW50X3llYXIiIH4gIkN1cnJlbnQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJub25fZWNpZ19jdXJyZW50X3llYXIiIH4gIkN1cnJlbnQiKSkgJT4lCiAgICBtdXRhdGUoUHJvZHVjdCA9IGNhc2Vfd2hlbihDYXRlZ29yeSA9PSJlY2lnX2V2ZXJfeWVhciIgfiAiRS1jaWdhcmV0dGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0ibm9uX2VjaWdfZXZlcl95ZWFyIiB+ICJPdGhlciBwcm9kdWN0cyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09ImVjaWdfY3VycmVudF95ZWFyIiB+ICJFLWNpZ2FyZXR0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJub25fZWNpZ19jdXJyZW50X3llYXIiIH4gIk90aGVyIHByb2R1Y3RzIikpICU+JQogICAgZmlsdGVyKFVzZXI9PSJFdmVyIikgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcix5PWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwgY29sb3I9UHJvZHVjdCkpICsKICAgIGdlb21fbGluZShsaW5ldHlwZT0xKSArICMgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIsIGNvbG9yPSJibGFjayIpICsKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwLCA2MCwgYnkgPSAxMCksIGxpbWl0cyA9IGMoMTAsNjApKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiSG93IGRvZXMgZS1jaWdhcmV0dGUgZXZlciB1c2UgY29tcGFyZSB0byBldmVyIHVzZSBvZiBvdGhlciBwcm9kdWN0cyBvdmVyIHRoZSB5ZWFycz8iLAogICAgICAgICBzdWJ0aXRsZSA9ICJFLWNpZ2FyZXR0ZSBhbmQgbm9uLWUtY2lnYXJldHRlIHVzZSIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90NwpgYGAKCmBgYHtyfQpwbG90OCA8LSBueXRzX2RhdGEgJT4lCiAgICBtdXRhdGUoZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBFRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIENFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1DRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUoZWNpZ19ldmVyID0gY2FzZV93aGVuKGVjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfZXZlciA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogICAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgICBzdW1tYXJpc2UoZWNpZ19ldmVyX3llYXI9KHN1bShlY2lnX2V2ZXIsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoZWNpZ19ldmVyKSksCiAgICAgICAgICAgICAgZWNpZ19jdXJyZW50X3llYXI9KHN1bShlY2lnX2N1cnJlbnQsIG5hLnJtID0gVFJVRSkqMTAwKS8KICAgICAgICAgICAgICAgIHN1bSghaXMubmEoZWNpZ19jdXJyZW50KSksCiAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyPShzdW0obm9uX2VjaWdfZXZlciwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShub25fZWNpZ19ldmVyKSksCiAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyPShzdW0obm9uX2VjaWdfY3VycmVudCwgbmEucm0gPSBUUlVFKSoxMDApLwogICAgICAgICAgICAgICAgc3VtKCFpcy5uYShub25fZWNpZ19jdXJyZW50KSkpICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiQ2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpICU+JQogICAgIyBnYXRoZXIoa2V5PUNhdGVnb3J5LAogICAgIyAgICAgICAgdmFsdWU9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLAogICAgIyAgICAgICAgLXllYXIpICU+JQogICAgbXV0YXRlKFVzZXIgPSBjYXNlX3doZW4oQ2F0ZWdvcnkgPT0iZWNpZ19ldmVyX3llYXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJub25fZWNpZ19ldmVyX3llYXIiIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJlY2lnX2N1cnJlbnRfeWVhciIgfiAiQ3VycmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2N1cnJlbnRfeWVhciIgfiAiQ3VycmVudCIpKSAlPiUKICAgIG11dGF0ZShQcm9kdWN0ID0gY2FzZV93aGVuKENhdGVnb3J5ID09ImVjaWdfZXZlcl95ZWFyIiB+ICJFLWNpZ2FyZXR0ZXMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBDYXRlZ29yeSA9PSJub25fZWNpZ19ldmVyX3llYXIiIH4gIk90aGVyIHByb2R1Y3RzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2F0ZWdvcnkgPT0iZWNpZ19jdXJyZW50X3llYXIiIH4gIkUtY2lnYXJldHRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIENhdGVnb3J5ID09Im5vbl9lY2lnX2N1cnJlbnRfeWVhciIgfiAiT3RoZXIgcHJvZHVjdHMiKSkgJT4lCiAgICBnZ3Bsb3QoYWVzKHg9eWVhcix5PWBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCwgY29sb3I9UHJvZHVjdCwgbGluZXR5cGU9VXNlcikpICsKICAgIGdlb21fbGluZSgpICsKICBnZW9tX3BvaW50KHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzID0gYygyLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA2MCwgYnkgPSAxMCksIGxpbWl0cyA9IGMoMCw2MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICJIb3cgZG9lcyBlLWNpZ2FyZXR0ZSB1c2UgY29tcGFyZSB0byB1c2Ugb2Ygb3RoZXIgcHJvZHVjdHMgb3ZlciB0aGUgeWVhcnM/IiwKICAgICAgICAgc3VidGl0bGUgPSAiRS1jaWdhcmV0dGUgYW5kIG5vbi1lLWNpZ2FyZXR0ZSB1c2UiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKcGxvdDgKYGBgCgojIyMgVW53ZWlnaHRlZCBTYW1wbGUKCmBgYHtyLCBmaWcuaGVpZ2h0PTEwfQpwbG90QV91dyA8LSBwbG90MSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogICAgbGFicyh0aXRsZSA9ICJOaWNvdGluZSBwcm9kdWN0IHVzZXJzIG1vcmUgcHJldmFsZW50IGFmdGVyIDIwMTciLAogICAgICAgICBzdWJ0aXRsZSA9IE5VTEwsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90Ql91dyA8LSBwbG90NyArIAogIHRoZW1lKGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICAgIGxhYnModGl0bGUgPSAiJSBFdmVyIHRyeWluZyBlLWNpZ2FyZXR0ZXMgaW5jcmVhc2VzICZcbiUgZXZlciB0cnlpbmcgb3RoZXIgcHJvZHVjdHMgZGVjcmVhc2VzIiwKICAgICAgICAgc3VidGl0bGUgPSBOVUxMLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKcGxvdENfdXcgPC0gcGxvdDggKyAKICB0aGVtZShheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICBsYWJzKHRpdGxlID0gIiUgVXNpbmcgZS1jaWdhcmV0dGVzIGluY3JlYXNlcyAmXG4lIHVzaW5nIE90aGVyIHByb2R1Y3RzIGRlY3JlYXNlcyIsCiAgICAgICAgIHN1YnRpdGxlID0gTlVMTCwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnRpdGxlX3V3IDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgICJIYXZlIHZhcGluZyByYXRlcyBwb3NzaWJseSBpbmZsdWVuY2VkIHRvYmFjY28vbmljb3RpbmUgdXNlPyIsCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTQsCiAgICB4ID0gMCwKICAgIGhqdXN0ID0gMAogICkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpwbG90c0FfdXcgPC0gcGxvdF9ncmlkKHBsb3RBX3V3LAogICAgICAgICAgICAgICAgICAgICByZWxfd2lkdGhzID0gYygxLDEpKQpwbG90c0JDX3V3IDwtIHBsb3RfZ3JpZChwbG90Ql91dywKICAgICAgICAgICAgICAgICAgICAgICAgcGxvdENfdXcsCiAgICAgICAgICAgICAgICAgICAgICAgIHJlbF93aWR0aHMgPSBjKDEsMSkpCgpsZWdlbmRfdXcgPC0gZ2V0X2xlZ2VuZChwbG90Ql91dyArCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikpCgpmaWd1cmVfdXcgPC0gcGxvdF9ncmlkKHRpdGxlX3V3LAogICAgICAgICAgICAgICAgICAgICAgIHBsb3RzQV91dywKICAgICAgICAgICAgICAgICAgICAgICBwbG90c0JDX3V3LAogICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZF91dywKICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMSwKICAgICAgICAgICAgICAgICAgICAgICByZWxfaGVpZ2h0cyA9IGMoMC4xLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEpLAogICAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gMS4wKQoKZmlndXJlX3V3CmBgYAoKIyMjIFdlaWdodGVkIFNhbXBsZQoKYGBge3J9CnBsb3RBX3cgPC0gbnl0c19kYXRhICU+JQogICAgbXV0YXRlKHRvYmFjY29fc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgdG9iYWNjb19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUodG9iYWNjb19ldmVyID0gY2FzZV93aGVuKHRvYmFjY29fc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9iYWNjb19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgdG9iYWNjb19jdXJyZW50ID0gY2FzZV93aGVuKHRvYmFjY29fc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9iYWNjb19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogIGFzX3N1cnZleV9kZXNpZ24oc3RyYXRhID0gc3RyYXR1bSwgaWRzID0gcHN1LCB3ZWlnaHQgID0gZmlud2d0LCBuZXN0PVRSVUUpICU+JQogICAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgc3VtbWFyaXNlKHRvYmFjY29fZXZlcl95ZWFyID0gc3VydmV5X21lYW4odG9iYWNjb19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIHRvYmFjY29fY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4odG9iYWNjb19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSkpICAlPiUKICBtdXRhdGVfYXQodmFycygteWVhciksICIqIiwgMTAwKSAlPiUKICAgIHBpdm90X2xvbmdlcihjb2xzID0gLXllYXIsIG5hbWVzX3RvID0gIlR5cGUiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpICU+JQogICAgIyBnYXRoZXIoa2V5PVR5cGUsCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgJT4lCiAgbXV0YXRlKEVzdGltYXRlID0gY2FzZV93aGVuKGdyZXBsKCJfbG93IiwgVHlwZSkgfiAiTG93ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJfdXBwIiwgVHlwZSkgfiAiVXBwZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiTWVhbiIpLAogICAgICAgICBVc2VyID0gY2FzZV93aGVuKGdyZXBsKCJldmVyIiwgVHlwZSkgfiAiRXZlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoImN1cnJlbnQiLCBUeXBlKSB+ICJDdXJyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk1lYW4iKSkgJT4lCiAgZHBseXI6OnNlbGVjdCgtVHlwZSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IEVzdGltYXRlLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCkgJT4lCiAgI3NwcmVhZChFc3RpbWF0ZSwgYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICBnZ3Bsb3QoYWVzKHg9eWVhcix5PU1lYW4pKSArCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZT1Vc2VyKSkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluID0gTG93ZXIsIHltYXggPSBVcHBlciksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzID0gYygyLDEpKSArCiAgICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsNzAsYnk9MTApLAogICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgwLDcwLGJ5PTEwKSwKICAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsNzApKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIk5pY290aW5lIHByb2R1Y3QgdXNlcnMgbW9yZSBwcmV2YWxlbnQgYWZ0ZXIgMjAxNyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgpwbG90Ql93IDwtIG55dHNfZGF0YSAlPiUKICAgIG11dGF0ZShlY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIEVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1FRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiQyIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUNFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpKSAlPiUKICAgIG11dGF0ZShlY2lnX2V2ZXIgPSBjYXNlX3doZW4oZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBlY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4oZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19ldmVyID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID09MCB+IEZBTFNFKSwKICAgICAgICAgICBub25fZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKG5vbl9lY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID09MCB+IEZBTFNFKSkgJT4lCiAgYXNfc3VydmV5X2Rlc2lnbihzdHJhdGEgPSBzdHJhdHVtLCBpZHMgPSBwc3UsIHdlaWdodCAgPSBmaW53Z3QsIG5lc3Q9VFJVRSkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICAgIHN1bW1hcmlzZShlY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKGVjaWdfZXZlciwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICBlY2lnX2N1cnJlbnRfeWVhciA9IHN1cnZleV9tZWFuKGVjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICBub25fZWNpZ19ldmVyX3llYXIgPSBzdXJ2ZXlfbWVhbihub25fZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnRfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2N1cnJlbnQsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoLXllYXIpLCAiKiIsIDEwMCkgJT4lCiAgZHBseXI6OnNlbGVjdCh5ZWFyLAogICAgICAgICAgICAgICAgZWNpZ19ldmVyX3llYXIsCiAgICAgICAgICAgICAgICBlY2lnX2N1cnJlbnRfeWVhciwKICAgICAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnRfeWVhciwKICAgICAgICAgICAgICAgIGNvbnRhaW5zKCJsb3ciKSwKICAgICAgICAgICAgICAgIGNvbnRhaW5zKCJ1cHAiKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiQ2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpICU+JQogICAgIyBnYXRoZXIoa2V5PUNhdGVnb3J5LAogICAgIyAgICAgICAgdmFsdWU9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLAogICAgIyAgICAgICAgLXllYXIpICAlPiUKICBtdXRhdGUoRXN0aW1hdGUgPSBjYXNlX3doZW4oZ3JlcGwoIl9sb3ciLCBDYXRlZ29yeSkgfiAiTG93ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJfdXBwIiwgQ2F0ZWdvcnkpIH4gIlVwcGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk1lYW4iKSwKICAgICAgICAgVXNlciA9IGNhc2Vfd2hlbihncmVwbCgiY3VycmVudCIsIENhdGVnb3J5KSB+ICJDdXJyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkV2ZXIiLCksCiAgICAgICAgIFByb2R1Y3QgPSBjYXNlX3doZW4oZ3JlcGwoIm5vbl9lY2lnIiwgQ2F0ZWdvcnkpIH4gIk90aGVyIHByb2R1Y3RzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkUtY2lnYXJldHRlcyIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1DYXRlZ29yeSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IEVzdGltYXRlLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCkgJT4lCiAgI3NwcmVhZChFc3RpbWF0ZSwgYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICBmaWx0ZXIoVXNlcj09IkV2ZXIiKSAlPiUKICBkcGx5cjo6cmVuYW1lKCJMb3dlcl90ZW1wIiA9IFVwcGVyLAogICAgICAgICAgICAgICAgIlVwcGVyX3RlbXAiID0gTG93ZXIpICU+JQogIGRwbHlyOjpyZW5hbWUoIkxvd2VyIj1Mb3dlcl90ZW1wLAogICAgICAgICAgICAgICAgIlVwcGVyIj1VcHBlcl90ZW1wKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9TWVhbiwgY29sb3I9UHJvZHVjdCkpICsKICBnZW9tX2xpbmUobGluZXR5cGU9MSkgKwogIGdlb21fbGluZXJhbmdlKGFlcyh5bWluID0gTG93ZXIsIHltYXggPSBVcHBlciksIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDEwLCA2MCwgYnkgPSAxMCksIGxpbWl0cyA9IGMoMTAsNjApKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpKSArCiAgICBsYWJzKHRpdGxlID0gIiUgZXZlciB0cnlpbmcgZS1jaWdhcmV0dGVzIGluY3JlYXNlcyAmXG4lIGV2ZXIgdHJ5aW5nIG90aGVyIHByb2R1Y3RzIGRlY3JlYXNlcyIsCiAgICAgICAgIHkgPSAiJSBvZiBzdHVkZW50cyIpCgojIyMjIHRoZSB3cmFuZ2xpbmcgbG9va3MgdGhlIHNhbWUgYXMgdGhlIGFib3ZlIHBsb3QuLi4KcGxvdENfdyA8LSBueXRzX2RhdGEgJT4lCiAgICBtdXRhdGUoZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBFRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIENFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1DRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUoZWNpZ19ldmVyID0gY2FzZV93aGVuKGVjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfZXZlciA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogIGFzX3N1cnZleV9kZXNpZ24oc3RyYXRhID0gc3RyYXR1bSwgaWRzID0gcHN1LCB3ZWlnaHQgID0gZmlud2d0LCBuZXN0PVRSVUUpICU+JQogICAgZ3JvdXBfYnkoeWVhcikgJT4lCiAgc3VtbWFyaXNlKGVjaWdfZXZlcl95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4oZWNpZ19jdXJyZW50LCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyID0gc3VydmV5X21lYW4obm9uX2VjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpKSAlPiUKICBtdXRhdGVfYXQodmFycygteWVhciksICIqIiwgMTAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KHllYXIsCiAgICAgICAgICAgICAgICBlY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIGVjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfZXZlcl95ZWFyLAogICAgICAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudF95ZWFyLAogICAgICAgICAgICAgICAgY29udGFpbnMoImxvdyIpLAogICAgICAgICAgICAgICAgY29udGFpbnMoInVwcCIpKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IC15ZWFyLCBuYW1lc190byA9ICJDYXRlZ29yeSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIikgJT4lCiAgICAjIGdhdGhlcihrZXk9Q2F0ZWdvcnksCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgJT4lCiAgICBtdXRhdGUoRXN0aW1hdGUgPSBjYXNlX3doZW4oZ3JlcGwoIl9sb3ciLCBDYXRlZ29yeSkgfiAiTG93ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJfdXBwIiwgQ2F0ZWdvcnkpIH4gIlVwcGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk1lYW4iKSwKICAgICAgICAgVXNlciA9IGNhc2Vfd2hlbihncmVwbCgiZXZlciIsIENhdGVnb3J5KSB+ICJFdmVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiY3VycmVudCIsIENhdGVnb3J5KSB+ICJDdXJyZW50IiksCiAgICAgICAgIFByb2R1Y3QgPSBjYXNlX3doZW4oZ3JlcGwoIm5vbl9lY2lnIiwgQ2F0ZWdvcnkpIH4gIk90aGVyIHByb2R1Y3RzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkUtY2lnYXJldHRlcyIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1DYXRlZ29yeSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IEVzdGltYXRlLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCkgJT4lCiAgI3NwcmVhZChFc3RpbWF0ZSwgYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9TWVhbiwgY29sb3I9UHJvZHVjdCkpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlPVVzZXIpKSArCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKHltaW4gPSBMb3dlciwgeW1heCA9IFVwcGVyKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygwLDYwKSkgKwogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogICAgbGFicyh0aXRsZSA9ICIlIFVzaW5nIGUtY2lnYXJldHRlcyBpbmNyZWFzZXMgJlxuJSB1c2luZyBPdGhlciBwcm9kdWN0cyBkZWNyZWFzZXMiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKdGl0bGVfdyA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICBleHByZXNzaW9uKCJIYXZlIHZhcGluZyByYXRlcyBwb3NzaWJseSBpbmZsdWVuY2VkIHRvYmFjY28vbmljb3RpbmUgdXNlPyIpLAogICAgZm9udGZhY2UgPSAnYm9sZCcsCiAgICBzaXplPTE0LAogICAgeCA9IDAsCiAgICBoanVzdCA9IDAKICApICsKICB0aGVtZSgKICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAsIDAsIDAsIDApCiAgKQoKcGxvdHNBX3cgPC0gcGxvdF9ncmlkKHBsb3RBX3csCiAgICAgICAgICAgICAgICAgICAgIHJlbF93aWR0aHMgPSBjKDEpLAogICAgICAgICAgICAgICAgICAgICBhbGlnbiA9ICJ2IiwKICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCnBsb3RzQkNfdyA8LSBwbG90X2dyaWQocGxvdEJfdywKICAgICAgICAgICAgICAgICAgICAgcGxvdENfdywKICAgICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMSwxKSwKICAgICAgICAgICAgICAgICAgICAgYWxpZ24gPSAidiIsCiAgICAgICAgICAgICAgICAgICAgIGF4aXMgPSAiYnQiKQoKbGVnZW5kX3cgPC0gZ2V0X2xlZ2VuZChwbG90Ql93ICsKICAgICAgICAgICAgICAgICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiKSkKCmZpZ3VyZV93IDwtIHBsb3RfZ3JpZCh0aXRsZV93LAogICAgICAgICAgICAgICAgICAgICAgcGxvdHNBX3csCiAgICAgICAgICAgICAgICAgICAgICBwbG90c0JDX3csCiAgICAgICAgICAgICAgICAgICAgICBsZWdlbmRfdywKICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAxLAogICAgICAgICAgICAgICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDAuMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMC4xKSwKICAgICAgICAgICAgICAgICAgICAgIHNjYWxlID0gMS4wKQoKZmlndXJlX3cKYGBgCgojIyMgSHlwb3RoZXRoaWNhbCBDb2hvcnQKCmBgYHtyfQpwbG90QV93XzggPC0gbnl0c19kYXRhICU+JQogIGZpbHRlcigoR3JhZGUgPT0gIjgiICYgeWVhciA9PSAyMDE1KSB8CiAgICAgICAgIChHcmFkZSA9PSAiOSIgJiB5ZWFyID09IDIwMTYpIHwKICAgICAgICAgKEdyYWRlID09ICIxMCIgJiB5ZWFyID09IDIwMTcpIHwKICAgICAgICAgKEdyYWRlID09ICIxMSIgJiB5ZWFyID09IDIwMTgpIHwKICAgICAgICAgIChHcmFkZSA9PSAiMTIiICYgeWVhciA9PSAyMDE5KSAKICAgICAgICAgKSAlPiUKICAgIG11dGF0ZSh0b2JhY2NvX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIHRvYmFjY29fc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSkpICU+JQogICAgbXV0YXRlKHRvYmFjY29fZXZlciA9IGNhc2Vfd2hlbih0b2JhY2NvX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvYmFjY29fc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIHRvYmFjY29fY3VycmVudCA9IGNhc2Vfd2hlbih0b2JhY2NvX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvYmFjY29fc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpKSAlPiUKICBhc19zdXJ2ZXlfZGVzaWduKHN0cmF0YSA9IHN0cmF0dW0sIGlkcyA9IHBzdSwgd2VpZ2h0ICA9IGZpbndndCkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICBzdW1tYXJpc2UodG9iYWNjb19ldmVyX3llYXIgPSBzdXJ2ZXlfbWVhbih0b2JhY2NvX2V2ZXIsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICAgdG9iYWNjb19jdXJyZW50X3llYXIgPSBzdXJ2ZXlfbWVhbih0b2JhY2NvX2N1cnJlbnQsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSkgICU+JQogIG11dGF0ZV9hdCh2YXJzKC15ZWFyKSwgIioiLCAxMDApICU+JQogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiVHlwZSIsIHZhbHVlc190byA9ICJQZXJjZW50YWdlIG9mIHN0dWRlbnRzIiklPiUKICAgICMgZ2F0aGVyKGtleT1UeXBlLAogICAgIyAgICAgICAgdmFsdWU9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLAogICAgIyAgICAgICAgLXllYXIpICU+JQogIG11dGF0ZShFc3RpbWF0ZSA9IGNhc2Vfd2hlbihncmVwbCgiX2xvdyIsIFR5cGUpIH4gIkxvd2VyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiX3VwcCIsIFR5cGUpIH4gIlVwcGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk1lYW4iKSwKICAgICAgICAgVXNlciA9IGNhc2Vfd2hlbihncmVwbCgiZXZlciIsIFR5cGUpIH4gIkV2ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJjdXJyZW50IiwgVHlwZSkgfiAiQ3VycmVudCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJNZWFuIikpICU+JQogIGRwbHlyOjpzZWxlY3QoLVR5cGUpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBFc3RpbWF0ZSwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBgUGVyY2VudGFnZSBvZiBzdHVkZW50c2ApICU+JQogICNzcHJlYWQoRXN0aW1hdGUsIGBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXIseT1NZWFuKSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGU9VXNlcikpICsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IExvd2VyLCB5bWF4ID0gVXBwZXIpKSArIAogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKDIsMSkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCw3MCxieT0xMCksCiAgICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDAsNzAsYnk9MTApLAogICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCw3MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiTmljb3RpbmUgcHJvZHVjdCB1c2VycyBiZWNvbWluZyBpbmNyZWFzaW5nbHkgcHJldmFsZW50IiwKICAgICAgICAgeSA9ICIlIG9mIHN0dWRlbnRzIikKCnBsb3RCX3dfOCA8LSBueXRzX2RhdGEgJT4lCiAgZmlsdGVyKChHcmFkZSA9PSAiOCIgJiB5ZWFyID09IDIwMTUpIHwKICAgICAgICAgKEdyYWRlID09ICI5IiAmIHllYXIgPT0gMjAxNikgfAogICAgICAgICAoR3JhZGUgPT0gIjEwIiAmIHllYXIgPT0gMjAxNykgfAogICAgICAgICAoR3JhZGUgPT0gIjExIiAmIHllYXIgPT0gMjAxOCkgfAogICAgICAgICAgKEdyYWRlID09ICIxMiIgJiB5ZWFyID09IDIwMTkpIAogICAgICAgICApICU+JQogICAgbXV0YXRlKGVjaWdfc3VtX2V2ZXIgPSBzZWxlY3QoLiwgRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9IHNlbGVjdCguLCBDRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBzdGFydHNfd2l0aCgiRSIsIGlnbm9yZS5jYXNlID0gRkFMU0UpKSAlPiUKICAgICAgICAgICAgICAgc2VsZWN0KC4sLUVFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJDIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtQ0VMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSkpICU+JQogICAgbXV0YXRlKGVjaWdfZXZlciA9IGNhc2Vfd2hlbihlY2lnX3N1bV9ldmVyID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIGVjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihlY2lnX3N1bV9jdXJyZW50ID4gMCB+IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjaWdfc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX2V2ZXIgPSBjYXNlX3doZW4obm9uX2VjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfc3VtX2V2ZXIgPT0wIH4gRkFMU0UpLAogICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnQgPSBjYXNlX3doZW4obm9uX2VjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPT0wIH4gRkFMU0UpKSAlPiUKICBhc19zdXJ2ZXlfZGVzaWduKHN0cmF0YSA9IHN0cmF0dW0sIGlkcyA9IHBzdSwgd2VpZ2h0ICA9IGZpbndndCkgJT4lCiAgICBncm91cF9ieSh5ZWFyKSAlPiUKICAgIHN1bW1hcmlzZShlY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKGVjaWdfZXZlciwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICBlY2lnX2N1cnJlbnRfeWVhciA9IHN1cnZleV9tZWFuKGVjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICBub25fZWNpZ19ldmVyX3llYXIgPSBzdXJ2ZXlfbWVhbihub25fZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnRfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2N1cnJlbnQsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoLXllYXIpLCAiKiIsIDEwMCkgJT4lCiAgZHBseXI6OnNlbGVjdCh5ZWFyLAogICAgICAgICAgICAgICAgZWNpZ19ldmVyX3llYXIsCiAgICAgICAgICAgICAgICBlY2lnX2N1cnJlbnRfeWVhciwKICAgICAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnRfeWVhciwKICAgICAgICAgICAgICAgIGNvbnRhaW5zKCJsb3ciKSwKICAgICAgICAgICAgICAgIGNvbnRhaW5zKCJ1cHAiKSkgJT4lCiAgIHBpdm90X2xvbmdlcihjb2xzID0gLXllYXIsIG5hbWVzX3RvID0gIkNhdGVnb3J5IiwgdmFsdWVzX3RvID0gIlBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHMiKSU+JQogICAgIyBnYXRoZXIoa2V5PUNhdGVnb3J5LAogICAgIyAgICAgICAgdmFsdWU9YFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgLAogICAgIyAgICAgICAgLXllYXIpICAlPiUKICBtdXRhdGUoRXN0aW1hdGUgPSBjYXNlX3doZW4oZ3JlcGwoIl9sb3ciLCBDYXRlZ29yeSkgfiAiTG93ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJfdXBwIiwgQ2F0ZWdvcnkpIH4gIlVwcGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk1lYW4iKSwKICAgICAgICAgVXNlciA9IGNhc2Vfd2hlbihncmVwbCgiY3VycmVudCIsIENhdGVnb3J5KSB+ICJDdXJyZW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkV2ZXIiLCksCiAgICAgICAgIFByb2R1Y3QgPSBjYXNlX3doZW4oZ3JlcGwoIm5vbl9lY2lnIiwgQ2F0ZWdvcnkpIH4gIk90aGVyIHByb2R1Y3RzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkUtY2lnYXJldHRlcyIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1DYXRlZ29yeSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IEVzdGltYXRlLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCkgJT4lCiAgI3NwcmVhZChFc3RpbWF0ZSwgYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICBmaWx0ZXIoVXNlcj09IkV2ZXIiKSAlPiUKICBkcGx5cjo6cmVuYW1lKCJMb3dlcl90ZW1wIiA9IFVwcGVyLAogICAgICAgICAgICAgICAgIlVwcGVyX3RlbXAiID0gTG93ZXIpICU+JQogIGRwbHlyOjpyZW5hbWUoIkxvd2VyIj1Mb3dlcl90ZW1wLAogICAgICAgICAgICAgICAgIlVwcGVyIj1VcHBlcl90ZW1wKSAlPiUKICBnZ3Bsb3QoYWVzKHg9eWVhcix5PU1lYW4sIGNvbG9yPVByb2R1Y3QpKSArCiAgZ2VvbV9saW5lKGxpbmV0eXBlPTEpICsKICBnZW9tX2xpbmVyYW5nZShhZXMoeW1pbiA9IExvd2VyLCB5bWF4ID0gVXBwZXIpKSArIAogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMTAsIDYwLCBieSA9IDEwKSwgbGltaXRzID0gYygxMCw2MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiJSBldmVyIHRyeWluZyBuaWNvdGluZSBwcm9kdWN0cyBpbmNyZWFzZXMiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKcGxvdENfd184IDwtIG55dHNfZGF0YSAlPiUKICBmaWx0ZXIoKEdyYWRlID09ICI4IiAmIHllYXIgPT0gMjAxNSkgfAogICAgICAgICAoR3JhZGUgPT0gIjkiICYgeWVhciA9PSAyMDE2KSB8CiAgICAgICAgIChHcmFkZSA9PSAiMTAiICYgeWVhciA9PSAyMDE3KSB8CiAgICAgICAgIChHcmFkZSA9PSAiMTEiICYgeWVhciA9PSAyMDE4KSB8CiAgICAgICAgICAoR3JhZGUgPT0gIjEyIiAmIHllYXIgPT0gMjAxOSkgCiAgICAgICAgICkgJT4lCiAgICBtdXRhdGUoZWNpZ19zdW1fZXZlciA9IHNlbGVjdCguLCBFRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSwKICAgICAgICAgICBlY2lnX3N1bV9jdXJyZW50ID0gc2VsZWN0KC4sIENFTENJR1QpICU+JQogICAgICAgICAgICAgICBhcHBseSgxLCBzdW0sIG5hLnJtPVRSVUUpLAogICAgICAgICAgIG5vbl9lY2lnX3N1bV9ldmVyID0gc2VsZWN0KC4sIHN0YXJ0c193aXRoKCJFIiwgaWdub3JlLmNhc2UgPSBGQUxTRSkpICU+JQogICAgICAgICAgICAgICBzZWxlY3QoLiwtRUVMQ0lHVCkgJT4lCiAgICAgICAgICAgICAgIGFwcGx5KDEsIHN1bSwgbmEucm09VFJVRSksCiAgICAgICAgICAgbm9uX2VjaWdfc3VtX2N1cnJlbnQgPSBzZWxlY3QoLiwgc3RhcnRzX3dpdGgoIkMiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkgJT4lCiAgICAgICAgICAgICAgIHNlbGVjdCguLC1DRUxDSUdUKSAlPiUKICAgICAgICAgICAgICAgYXBwbHkoMSwgc3VtLCBuYS5ybT1UUlVFKSkgJT4lCiAgICBtdXRhdGUoZWNpZ19ldmVyID0gY2FzZV93aGVuKGVjaWdfc3VtX2V2ZXIgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgZWNpZ19jdXJyZW50ID0gY2FzZV93aGVuKGVjaWdfc3VtX2N1cnJlbnQgPiAwIH4gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfZXZlciA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fZXZlciA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fZXZlciA9PTAgfiBGQUxTRSksCiAgICAgICAgICAgbm9uX2VjaWdfY3VycmVudCA9IGNhc2Vfd2hlbihub25fZWNpZ19zdW1fY3VycmVudCA+IDAgfiBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub25fZWNpZ19zdW1fY3VycmVudCA9PTAgfiBGQUxTRSkpICU+JQogIGFzX3N1cnZleV9kZXNpZ24oc3RyYXRhID0gc3RyYXR1bSwgaWRzID0gcHN1LCB3ZWlnaHQgID0gZmlud2d0KSAlPiUKICAgIGdyb3VwX2J5KHllYXIpICU+JQogIHN1bW1hcmlzZShlY2lnX2V2ZXJfeWVhciA9IHN1cnZleV9tZWFuKGVjaWdfZXZlciwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICBlY2lnX2N1cnJlbnRfeWVhciA9IHN1cnZleV9tZWFuKGVjaWdfY3VycmVudCwgdmFydHlwZSA9ICJjaSIsIG5hLnJtPVRSVUUpLAogICAgICAgICAgICBub25fZWNpZ19ldmVyX3llYXIgPSBzdXJ2ZXlfbWVhbihub25fZWNpZ19ldmVyLCB2YXJ0eXBlID0gImNpIiwgbmEucm09VFJVRSksCiAgICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnRfeWVhciA9IHN1cnZleV9tZWFuKG5vbl9lY2lnX2N1cnJlbnQsIHZhcnR5cGUgPSAiY2kiLCBuYS5ybT1UUlVFKSkgJT4lCiAgbXV0YXRlX2F0KHZhcnMoLXllYXIpLCAiKiIsIDEwMCkgJT4lCiAgZHBseXI6OnNlbGVjdCh5ZWFyLAogICAgICAgICAgICAgICAgZWNpZ19ldmVyX3llYXIsCiAgICAgICAgICAgICAgICBlY2lnX2N1cnJlbnRfeWVhciwKICAgICAgICAgICAgICAgIG5vbl9lY2lnX2V2ZXJfeWVhciwKICAgICAgICAgICAgICAgIG5vbl9lY2lnX2N1cnJlbnRfeWVhciwKICAgICAgICAgICAgICAgIGNvbnRhaW5zKCJsb3ciKSwKICAgICAgICAgICAgICAgIGNvbnRhaW5zKCJ1cHAiKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiQ2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAiUGVyY2VudGFnZSBvZiBzdHVkZW50cyIpJT4lCiAgICAjIGdhdGhlcihrZXk9Q2F0ZWdvcnksCiAgICAjICAgICAgICB2YWx1ZT1gUGVyY2VudGFnZSBvZiBzdHVkZW50c2AsCiAgICAjICAgICAgICAteWVhcikgJT4lCiAgICBtdXRhdGUoRXN0aW1hdGUgPSBjYXNlX3doZW4oZ3JlcGwoIl9sb3ciLCBDYXRlZ29yeSkgfiAiTG93ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJfdXBwIiwgQ2F0ZWdvcnkpIH4gIlVwcGVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIk1lYW4iKSwKICAgICAgICAgVXNlciA9IGNhc2Vfd2hlbihncmVwbCgiZXZlciIsIENhdGVnb3J5KSB+ICJFdmVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiY3VycmVudCIsIENhdGVnb3J5KSB+ICJDdXJyZW50IiksCiAgICAgICAgIFByb2R1Y3QgPSBjYXNlX3doZW4oZ3JlcGwoIm5vbl9lY2lnIiwgQ2F0ZWdvcnkpIH4gIk90aGVyIHByb2R1Y3RzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIkUtY2lnYXJldHRlcyIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1DYXRlZ29yeSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IEVzdGltYXRlLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGBQZXJjZW50YWdlIG9mIHN0dWRlbnRzYCkgJT4lCiAgI3NwcmVhZChFc3RpbWF0ZSwgYFBlcmNlbnRhZ2Ugb2Ygc3R1ZGVudHNgKSAlPiUKICAgIGdncGxvdChhZXMoeD15ZWFyLHk9TWVhbiwgY29sb3I9UHJvZHVjdCkpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlPVVzZXIpKSArCiAgZ2VvbV9saW5lcmFuZ2UoYWVzKHltaW4gPSBMb3dlciwgeW1heCA9IFVwcGVyKSkgKyAKICBzY2FsZV9saW5ldHlwZV9tYW51YWwodmFsdWVzID0gYygyLDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCA2MCwgYnkgPSAxMCksIGxpbWl0cyA9IGMoMCw2MCkpICsKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCkpICsKICAgIGxhYnModGl0bGUgPSAiRS1jaWdhcmV0dGUgdXNlIHN1cnBhc3NlcyB1c2Ugb2Ygb3RoZXIgbmljb3RpbmUgcHJvZHVjdHMiLAogICAgICAgICB5ID0gIiUgb2Ygc3R1ZGVudHMiKQoKdGl0bGVfd184IDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgIGV4cHJlc3Npb24oIkFtb25nIn44XnRofiJncmFkZXJzIGluIDIwMTUsIGhhdmUgdmFwaW5nIHJhdGVzIHBvc3NpYmx5IGluZmx1ZW5jZWQgdG9iYWNjby9uaWNvdGluZSB1c2U/IiksCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTQsCiAgICB4ID0gMCwKICAgIGhqdXN0ID0gMAogICkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpwbG90c0Ffd184IDwtIHBsb3RfZ3JpZChwbG90QV93XzgsCiAgICAgICAgICAgICAgICAgICAgICAgIHJlbF93aWR0aHMgPSBjKDEpLAogICAgICAgICAgICAgICAgICAgICAgICBhbGlnbiA9ICJ2IiwKICAgICAgICAgICAgICAgICAgICAgICAgYXhpcyA9ICJidCIpCgpwbG90c0JDX3dfOCA8LSBwbG90X2dyaWQocGxvdEJfd184LAogICAgICAgICAgICAgICAgICAgICAgICAgcGxvdENfd184LAogICAgICAgICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMSwxKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMgPSAiYnQiKQoKbGVnZW5kX3dfOCA8LSBnZXRfbGVnZW5kKHBsb3RCX3dfOCArCiAgICAgICAgICAgICAgICAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikpCgpmaWd1cmVfd184IDwtIHBsb3RfZ3JpZCh0aXRsZV93XzgsCiAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RzQV93XzgsCiAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RzQkNfd184LAogICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmRfd184LAogICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDAuMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMC4xKSwKICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSAxLjAKKQoKZmlndXJlX3dfOApgYGAKCiMjIyBGaW5hbCBGaWd1cmUKCmBgYHtyfQp0aXRsZV9maW5hbCA8LSBnZ2RyYXcoKSArCiAgZHJhd19sYWJlbCgKICAgIGV4cHJlc3Npb24oIkhhdmUgdmFwaW5nIHJhdGVzIHBvc3NpYmx5IGluZmx1ZW5jZWQgdG9iYWNjby9uaWNvdGluZSB1c2U/IiksCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTYsCiAgICB4ID0gMC41KSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCnN1YnRpdGxlX3V3X2ZpbmFsIDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgIGV4cHJlc3Npb24ofjZedGh+Ii0ifjEyXnRofiJncmFkZXJzLCB1bndlaWdodGVkIiksCiAgICBzaXplPTEyLAogICAgeCA9IDAuNSkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpzdWJ0aXRsZV93X2ZpbmFsIDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgIGV4cHJlc3Npb24ofjZedGh+Ii0ifjEyXnRofiJncmFkZXJzLCB3ZWlnaHRlZCIpLAogICAgZm9udGZhY2UgPSAnYm9sZCcsCiAgICBzaXplPTEyLAogICAgeCA9IDAuNSkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpzdWJ0aXRsZV93XzhfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbih+OF50aH4iZ3JhZGVycyBpbiAyMDE1LCB3ZWlnaHRlZCIpLAogICAgZm9udGZhY2UgPSAnYm9sZCcsCiAgICBzaXplPTEyLAogICAgeCA9IDAuNSkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpzdWJ0aXRsZV9maW5hbCA8LSBwbG90X2dyaWQoc3VidGl0bGVfdXdfZmluYWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdWJ0aXRsZV93X2ZpbmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VidGl0bGVfd184X2ZpbmFsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMpCgpwbG90c0FfdGl0bGVfZmluYWwgPC0gZ2dkcmF3KCkgKyAKICBkcmF3X2xhYmVsKAogICAgZXhwcmVzc2lvbigiUHJldmFsZW5jZSBvZiBlLWNpZ2FyZXR0ZSB1c2UgYnkgdXNlciB0eXBlIiksCiAgICBzaXplPTE0LAogICAgeCA9IDAuNSkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpwbG90c0FfZmluYWwgPC0gcGxvdF9ncmlkKHBsb3RBX3V3ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdEFfdyArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RBX3dfOCArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMgPSAiYnQiKQoKcGxvdHNCX3RpdGxlX2ZpbmFsIDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgIGV4cHJlc3Npb24oIlByZXZhbGVuY2Ugb2YgZXZlciB1c2UgYnkgcHJvZHVjdCB0eXBlIiksCiAgICBzaXplPTE0LAogICAgeCA9IDAuNSkgKwogIHRoZW1lKAogICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMCwgMCwgMCwgMCkKICApCgpwbG90c0JfZmluYWwgPC0gcGxvdF9ncmlkKHBsb3RCX3V3ICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdEJfdyArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RCX3dfOCArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzLAogICAgICAgICAgICAgICAgICAgICAgICAgIGFsaWduID0gInYiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMgPSAiYnQiKQoKcGxvdHNDX3RpdGxlX2ZpbmFsIDwtIGdnZHJhdygpICsgCiAgZHJhd19sYWJlbCgKICAgIGV4cHJlc3Npb24oIlByZXZhbGVuY2Ugb2Ygbmljb3RpbmUgcHJvZHVjdCB1c2UgYnkgcHJvZHVjdCAmIHVzZXIgdHlwZSIpLAogICAgc2l6ZT0xNCwKICAgIHggPSAwLjUpICsKICB0aGVtZSgKICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAsIDAsIDAsIDApCiAgKQoKcGxvdHNDX2ZpbmFsIDwtIHBsb3RfZ3JpZChwbG90Q191dyArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHBsb3RDX3cgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwbG90Q193XzggKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF9ibGFuaygpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMywKICAgICAgICAgICAgICAgICAgICAgICAgICBhbGlnbiA9ICJ2IiwKICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzID0gImJ0IikKCmxlZ2VuZF9maW5hbCA8LSBnZXRfbGVnZW5kKHBsb3RCX3cgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIpKQoKZmluYWxfcGxvdCA8LSBwbG90X2dyaWQodGl0bGVfZmluYWwsCiAgICAgICAgICBwbG90c0FfdGl0bGVfZmluYWwsCiAgICAgICAgICBzdWJ0aXRsZV9maW5hbCwKICAgICAgICAgIHBsb3RzQV9maW5hbCwKICAgICAgICAgIHBsb3RzQl90aXRsZV9maW5hbCwKICAgICAgICAgIHN1YnRpdGxlX2ZpbmFsLAogICAgICAgICAgcGxvdHNCX2ZpbmFsLAogICAgICAgICAgcGxvdHNDX3RpdGxlX2ZpbmFsLAogICAgICAgICAgc3VidGl0bGVfZmluYWwsCiAgICAgICAgICBwbG90c0NfZmluYWwsCiAgICAgICAgICBsZWdlbmRfZmluYWwsCiAgICAgICAgICBuY29sID0gMSwKICAgICAgICAgIHJlbF9oZWlnaHRzID0gYygwLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMC4yLAogICAgICAgICAgICAgICAgICAgICAgICAgIDAuMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAxLAogICAgICAgICAgICAgICAgICAgICAgICAgIDAuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAwLjEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAwLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMC4xLAogICAgICAgICAgICAgICAgICAgICAgICAgIDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgMC4xKSkKCmZpbmFsX3Bsb3QKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KZ2dzYXZlKCJmaW5hbF9wbG90LnBuZyIpCmBgYAoKIyMgKipTdWdnZXN0ZWQgSG9tZXdvcmsqKgoqKiogCgo8c3R5bGU+CmRpdi5ibHVlIHsgYmFja2dyb3VuZC1jb2xvcjojZTZmMGZmOyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gImJsdWUiPgoKKyBBcHBseSBzdXJ2ZXkgd2VpZ2h0cyB0byBvbmUgb2YgdGhlIGZpZ3VyZXMgcHJvZHVjZWQgaW4gdGhpcyBjYXNlIHN0dWR5IGluIHdoaWNoIHdlaWdodGVkIGVzdGltYXRlcyB3ZXJlIG5vdCBwcm9kdWNlZC4gSW5jbHVkZSBlcnJvciBiYXJzIGluIHRoZSB1cGRhdGVkIGZpZ3VyZS4KICAgICsgRG9lcyB0aGUgZmlndXJlIGNoYW5nZSBhZnRlciB0aGUgYXBwbGljYXRpb24gb2Ygc3VydmV5IHdlaWdodHM/CiAgICArIElmIHNvLCBkZXNjcmliZSBob3cuIAorIFJlcHJvZHVjZSBgZmluYWxfcGxvdGAgYWJvdmUgZm9yIGEgZGlmZmVyZW50IGNvaG9ydCBvZiB5b3VyIGNob2ljZS4KCjwvZGl2PgoKIyMjIE5vdGVzCgpFdmVyIGFuZCBjdXJyZW50IHZhcmlhYmxlcyBhcmUgbGltaXRlZCB0byB0aG9zZSBzaGFyZWQgYnkgYWxsIHllYXJzIG9mIGRhdGEgaW5jbHVkZWQgaW4gdGhpcyBjYXNlIHN0dWR5LgoKYGBge3IsIGVjaG89RkFMU0V9CmtuaXRfdGltZV9lbmQgPC0gU3lzLnRpbWUoKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQprbml0X3RpbWUgPC0ga25pdF90aW1lX2VuZCAtIGtuaXRfdGltZV9zdGFydAprbml0X3RpbWVfbWVzc2FnZSA8LSBwYXN0ZSgiS25pdCB0aW1lOiIsCiAgICAgIHJvdW5kKGFzLm51bWVyaWMoa25pdF90aW1lKSAsMyksCiAgICAgIHVuaXRzKGtuaXRfdGltZSkKICAgICAgKQpgYGAKCjxwIHN0eWxlPSJjb2xvcjpyZWQiPk5ldyBjb2RlOiBgciBrbml0X3RpbWVfbWVzc2FnZWAuIFByZXZpb3VzIGNvZGU6IH4gMyBtLiA8L3A+CgojIyMgUHJvYmxlbXMKCkkgaGFkIGRpZmZpY3VsdHkgcHJvZHVjaW5nIGEgcGxvdCB0aGF0IHN1Y2NpbmN0bHkgcHJlc2VudGVkIGEgdHJlbmQuIEl0J3MgdmVyeSBlYXN5IHRvIHByb2R1Y2UgcGxvdHMgdGhhdCBhcmUgdmVyeSB1c2VmdWwgb25jZSBvbmUgaXMgZmFtaWxpYXIgd2l0aCB0aGUgZGF0YS4gU29tZSBwbG90cywgaG93ZXZlciwgY2Fubm90IHN0YW5kIGFsb25lIGFuZCBuZWVkIGFkZGl0aW9uYWwgY29udGV4dCB0byBiZSBjbGVhciBmb3IgdGhvc2Ugd2l0aG91dCBwcmlvciBrbm93bGVkZ2Ugb2YgdGhlIGRhdGEuIFdoZW4gSSBmaXJzdCBzaGFyZWQgYSBwbG90IEkgaGFkIGJlZW4gd29ya2luZyBvbiB3aXRoIG90aGVycywgaXQgYmVjYW1lIGNsZWFyIHRoYXQgaW4gbXkgZWZmb3J0IHRvIHByZXNlbnQgYSBjb21wbGljYXRlZCBpZGVhIGJyaWVmbHkgSSBoYWQgbGVmdCBvdXQgaW5mb3JtYXRpb24gdGhhdCB3b3VsZCBtYWtlIHRoZSB0cmVuZCBlYXNpbHkgaW50ZXJwcmV0YWJsZS4gVG8gc29sdmUgdGhpcyBpc3N1ZSwgSSBiZWdhbiB0byBwcmVzZW50IHZpc3VhbGl6YXRpb25zIG9mIHRoZSBkYXRhIGFsb25nc2lkZSBteSBvcmlnaW5hbCBwbG90LiBUaGUgZmluYWwgZmlndXJlIEkgY3JlYXRlZCBjb250YWluZWQgc2V2ZXJhbCBhZGRpdGlvbmFsIHBsb3RzLCBlYWNoIHByZXNlbnRpbmcgdGhlIHNhbWUgdHJlbmQgYXQgYSBkaWZmZXJlbnQgbGV2ZWwgdGhhbiBteSBpbml0aWFsIHBsb3QuCgpNeSAiY2VudGVycGllY2UiIHBsb3QgaXMgdGhlIG1pZGRsZSBwbG90IGluIGBmaW5hbF9wbG90YC4gVGhlIDggcGxvdHMgYXJvdW5kIGl0IGhlbHAgcHJvdmlkZSBhIHZlcnkgY2xlYXIgcGljdHVyZSBvZiB3aGF0IGlzIGdvaW5nIG9uIGluIHRoZSBVUyB3aXRoIHJlZ2FyZHMgdG8gZS1jaWdhcmV0dGUgdXNlIGFuZCBuaWNvdGluZSBwcm9kdWN0IHVzZSBhdCBsYXJnZS4gT24gaXRzIG93biwgaXQncyBkaWZmaWN1bHQgdG8gdW5kZXJzdGFuZCB0aGUgdHJlbmRzIGluIHRoZSBVUyBhbmQgaG93IGltcG9ydGFudCB0aGUgd2VpZ2h0aW5nIHNjaGVtZSBpcyBmb3IgaW5mZXJlbmNlLiBPbmNlIHlvdSBhZGQgdGhlIGxlZnQgYW5kIHJpZ2h0IGNvbHVtbnMsIGl0J3MgY2xlYXIgd2hhdCBpcyBnb2luZyBvbi4gCgoKCiMjICoqRGF0YSBBbmFseXNpcyoqCioqKiAKCiMjIyAqKmNvbnRlbnQgaGVhZGVyKioKKioqIAoKCgojIyAqKlN1bW1hcnkqKgoqKiogCgoKCiMjICoqSGVscGZ1bCBMaW5rcyoqCioqKiAKCnJldmlldyBvZiBbdGlkeW1vZGVsc10oaHR0cHM6Ly9ydmlld3MucnN0dWRpby5jb20vMjAxOS8wNi8xOS9hLWdlbnRsZS1pbnRyby10by10aWR5bW9kZWxzLyl7dGFyZ2V0PSJfYmxhbmsifSAKCmd1aWRlIGZvciBbcHJlcHJvY2Vzc2luZyB3aXRoIHJlY2lwZXNdKGh0dHA6Ly93d3cucmViZWNjYWJhcnRlci5jb20vYmxvZy8yMDE5LTA2LTA2X3ByZV9wcm9jZXNzaW5nLykKCgojIyAqKlNlc3Npb24gaW5mbyoqCioqKgoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCg==